俗话说得好,“虎父无犬子”、“龙生龙,凤生凤,老鼠的儿子会打洞”,这在一定程度上说明了继承的重要性。在面向对象编程中,继承是代码复用和设计复用的重要途径,是面向对象程序设计的重要特征之一,继承也是实现多态的必要条件之一。
设计一个新类时,如果可以继承一个已有的设计良好的类然后进行二次开发,无疑会大幅度减少开发工作量,并且可以很大程度地保证质量。在继承关系中,已有的类称为父类或基类,新设计的类称为子类或派生类。派生类可以继承父类的公有成员,但是不能继承其私有成员。如果需要在派生类中调用基类的方法,可以使用内置函数super()或者通过“基类名.方法名()”的方式实现这一目的。
任务:设计Person类,并根据Person派生Teacher类,分别创建Person类与Teacher类的对象。
1 #基类必须继承于object,否则在子类中将无法使用super()函数
2 class Person(object):
3 def __init__(self,name='',age=20,sex='man'):
4 self.setName(name) #通过调用方法进行初始化
5 self.setAge(age) #这样可以对参数进行更好的控制
6 self.setSex(sex)
7
8 def setName(self,name):
9 if not isinstance(name,str):
10 print('name must be string.')
11
12 #如果数据不合法,就使用默认值
13 self.__name = ''
14 return
15
16 self.__name = name
17
18 def setAge(self,age):
19 if type(age) != int:
20 print('age must be integer.')
21 self.__age = 20
22 return
23 self.__age = age
24
25 def setSex(self,sex):
26 if sex not in ('man','woman'):
27 print('sex must be "man" or "woman"')
28 self.__sex='man'
29 return
30 self.__sex=sex
31
32 def show(self):
33 print(self.__name,self.__age,self.__sex,sep=' ')
34
35
36 #派生类
37 class Teacher(Person):
38 def __init__(self,name='',age=30,sex='man',department='Computer'):
39 #调用基类构造方法初始化基类的私有数据成员
40 super(Teacher,self).__init__(name,age,sex)
41
42 #也可以这样初始化基类的私有数据成员
43 #Person.__init__(self,name,age,sex)
44
45 #初始化派生类的数据成员
46 self.setDepartment(department)
47
48 def setDepartment(self,department):
49 if type(department) != str:
50 print('department must be a string.')
51 self.__department='Computer'
52 return
53 self.__department = department
54
55 def show(self):
56 super(Teacher,self).show()
57 print(self.__department)
58
59
60 if __name__ == '__main__':
61 #创建基类对象
62 zhangsan = Person('Zhang San',19,'man')
63 zhangsan.show()
64 print('=' * 30)
65
66 #创建派生类对象
67 lisi = Teacher('Li si',32,'man','Math')
68 lisi.show()
69
70 #调用继承的方法修改年龄
71 lisi.setAge(40)
72 lisi.show()
小提示:Python支持多继承,如果父类中有相同的方法名,而在子类中使用时没有指定父类名,则Python解释器将从左向右按顺序进行搜索。
下面的代码完整地描述了类的继承机制,请认真体会构造函数、私有方法以及普通公开方法的继承原理。
1 class A():
2 def __init__(self):
3 self.__private()
4 self.public()
5
6 def __private(self):
7 print('__private() method of A')
8
9 def public(self):
10 print('publiec() method of A')
11
12 def __test(self):
13 print('__test() method of A')
14
15
16 class B(A): #注意B类没有构造函数
17 def __private(self):
18 print('__private() method of B')
19
20 def public(self):
21 print('public() method of B')
22
23 b = B() #创建派生类对象,由于B类没有构造函数,所以用父类的构造方法
24
25 #__private() method of A
26 #public() method of B
27
28
29 #b.__test() #由于__test()是A类的私有方法,且没有在A类的__init__()函数中。
30
31 class C(A):
32 def __init__(self):
33 self.__private()
34 self.public()
35
36 def __private(self):
37 print('__private()method of C')
38
39 def public(self):
40 print('public() method of C')
41
42 c = C()
43 #__private()method of C
44 #public() method of C
45
46 c.__test() #子类不能继承父类的私有成员方法
47 '''
48 Traceback (most recent call last):
49 File "C:/Users/dddd/PycharmProjects/untitled5/test1.py", line 46, in <module>
50 c.__test()
51 AttributeError: 'C' object has no attribute '__test'
52 '''
53
54
55 #感觉还不过瘾,我再从网上找找介绍类的继承的文章参考一下
56 #在python3中,基类的构造函数不会被自动调用,需要手动调用,同样的方法也是这样,需要手动调用。可以使用类名称+init方法,
也可以使用super语法进行调用。
拓展知识:所谓多态,是指基类的同一个方法在不同派生类对象中具有不同的表现和行为。龙生九子,各不相同。派生类继承了基类的行为和属性之后,还会增加某些特定的行为和属性,同时还可能会对继承来的某些行为进行一定的改变,这恰恰是多态的表现形式。在Python中主要通过重写基类的方法来实现多态。