在android studio中如何创建一个类来继承另外一个类_Python编程从入门到实践-连载8(类)...
面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为。 根据类来创建对象被称为实例化,这让你能够使用类的实例。 9.1 创建和使用类
使用类几乎可以模拟任何东西。下面来编写一个表示小狗的简单类Dog——它表示的不是特
定的小狗,而是任何小狗。对于大多数宠物狗,我们都知道些什么呢?它们都有名字和年龄;我
们还知道,大多数小狗还会蹲下和打滚。由于大多数小狗都具备上述两项信息(名字和年龄)和
两种行为(蹲下和打滚),我们的Dog类将包含它们。这个类让Python知道如何创建表示小狗的对
象。
9.1.1 创建 Dog 类
根据Dog类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下( sit())和打滚
( roll_over())的能力:
我们定义(class Dog())了一个名为Dog的类 :根据约定,在Python中,首字母大写的名称指的是类。
1. 方法__init__()
类中的函数称为方法 ,前面学到的有关函数的一切都适用于方法,就目前而言,唯一重要的差别是调用方法的方式。
方法__init__()是一个特殊的方法,每当你根据Dog类创建新实例时, Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通方法发生名称冲突。
__init__()定义成了包含三个形参: self、 name和age。在这个方法的定义中,形参self必不可少,还必须位于其他形参的前面。
Python调用这个__init__()方法来创建Dog实例时,将自动传入实参self。每个与类相关联的方法
调用都自动传递实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。 self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。 self.age = age的作用与此类似。 像这样可通过实例访问的变量称为属性 。
Dog类还定义了另外两个方法: sit()和roll_over()(见)。由于这些方法不需要额外的信
息,如名字或年龄,因此它们只有一个形参self。我们后面将创建的实例能够访问这些方法,换
句话说,它们都会蹲下和打滚。
9.1.2 根据类创建实例
创建一个表示特定小狗的实例:
1. 访问属性 要访问实例的属性,可使用句点表示法。
访问my_dog的属性 name的值:
在这里, Python先找到实例my_dog,再查找与这个实例相关联的属性name。在Dog类中引用这个属性时,使用的是self.name。在3处,我们使用同样的方法来获取属性age的值。
2. 调用方法
根据Dog类创建实例后,就可以使用句点表示法来调用Dog类中定义的任何方法。
要调用方法,可指定实例的名称(这里是my_dog)和要调用的方法,并用句点分隔它们 .遇到代码my_dog.sit()时, Python在类Dog中查找方法sit()并运行其代码。
3. 创建多个实例
可按需求根据类创建任意数量的实例 ,下面再创建一个名为your_dog的实例
在这个实例中,我们创建了两条小狗,它们分别名为Willie和Lucy。每条小狗都是一个独立
的实例,有自己的一组属性,能够执行相同的操作:
9.2 使用类和实例
类编写好后,你的大部分时间都将花在使用根据类创建的实例上。你需要执行的一个重要任务是修改实例的属性。你可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。
9.2.1 Car 类
编写一个表示汽车的类,它存储了有关汽车的信息,还有一个汇总这些信息的方法:
9.2.2 给属性指定默认值
类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。在有些情况下,如设置默认值时,在方法__init__()内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
添加一个名为odometer_reading的属性,其初始值总是为0。我们还添加了一个名为read_odometer()的方法,用于读取汽车的里程表:
当Python调用方法__init__()来创建新实例时,将像前一个示例一样以属性的方式存
储制造商、型号和生产年份。接下来, Python将创建一个名为odometer_reading的属性,并将其
初始值设置为0。
一开始汽车的里程为0:
9.2.3 修改属性的值
可以以三种不同的方式修改属性的值:直接通过实例进行修改;通过方法进行设置;通过方
法进行递增(增加特定的值)。
1. 直接修改属性的值
要修改属性的值,最简单的方式是通过实例直接访问它。 下面的代码直接将里程表读数设置
为23:
我们使用句点表示法来直接访问并设置汽车的属性odometer_reading。这行代码让Python在实例my_new_car中找到属性odometer_reading,并将该属性的值设置为23:
2. 通过方法修改属性的值
下面的示例演示了一个名为update_odometer()的方法:
可对方法update_odometer()进行扩展,使其在修改里程表读数时做些额外的工作。下面来添
加一些逻辑,禁止任何人将里程表读数往回调:
3. 通过方法对属性的值进行递增
以增加从购买到登记期间行驶的100英里 :
9.3 继承
编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,
而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
9.3.1 子类的方法__init__()
创建子类的实例时, Python首先需要完成的任务是给父类的所有属性赋值。为此,子类的方
法__init__()需要父类施以援手。
下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此我们可以在前面创建的Car类的基础上创建新类ElectricCar,这样我们就只需为电动汽车特有的属性和行为编写代码。
下面来创建一个简单的ElectricCar类版本,它具备Car类的所有功能:
9.3.3 给子类定义属性和方法
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
下面来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。我们将存储电
瓶容量,并编写一个打印电瓶描述的方法:
9.3.4 重写父类的方法
对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子
类中定义一个这样的方法,即它与要重写的父类方法同名。这样, Python将不会考虑这个父类方
法,而只关注你在子类中定义的相应方法。
假设Car类有一个名为fill_gas_tank()的方法,它对全电动汽车来说毫无意义,因此你可能
想重写它。下面演示了一种重写方式 :
如果有人对电动汽车调用方法fill_gas_tank(), Python将忽略Car类中的方法fill_gas_tank(),转而运行上述代码。使用继承时,可让子类保留从父类那里继承而来的精华,
并剔除不需要的糟粕。
9.3.5 将实例用作属性
使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文
件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。你可以将大
型类拆分成多个协同工作的小类
例如,不断给ElectricCar类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶
的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为Battery的
类中,并将一个Battery实例用作ElectricCar类的一个属性:
9.4 导入类
9.4.1 导入单个类
下面来创建另一个文件——my_car.py,在其中导入Car类并创建其实例:
import语句让Python打开模块car,并导入其中的Car类
9.4.2 在一个模块中存储多个类
新建一个名为my_electric_car.py的文件,导入ElectricCar类,并创建一辆电动汽
车了:
9.4.3 从一个模块中导入多个类
9.4.4 导入整个模块
导入整个模块,再使用句点表示法访问需要的类。这种导入方法很简单,代码也易
于阅读。由于创建类实例的代码都包含模块名,因此不会与当前文件使用的任何名称发生冲突。
9.4.5 导入模块中的所有类
要导入模块中的每个类,可使用下面的语法:
不推荐使用这种导入方式,其原因有二。首先,如果只要看一下文件开头的import语句,就
能清楚地知道程序使用了哪些类,将大有裨益;但这种导入方式没有明确地指出你使用了模块中
的哪些类。这种导入方式还可能引发名称方面的困惑。如果你不小心导入了一个与程序文件中其
他东西同名的类,将引发难以诊断的错误。这里之所以介绍这种导入方式,是因为虽然不推荐使
用这种方式,但你可能会在别人编写的代码中见到它。