继承和多态
继承和多态
继承
在面向对象编程中,当我们已经创建了一个类,而又想再创建一个与之相似的类,比如添加几个方法,或者修改原来的方法,这时我们不必从头开始,可以从原来的类派生出一个新的类,我们把原来的类称为父类或基类,而派生出的类称为子类,子类继承了父类的所有数据和方法。让我们看一个简单的例子,首先我们定义一个
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
现在,我们想创建一个
class Dog(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'WangWang.., I am %s. ' % self.name
可以看到,greet
方法不一样,我们完全没必要创建一个新的类,而是从
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s. ' % self.name
>>> animal = Animal('animal') # 创建 animal 实例
>>> animal.greet()
Hello, I am animal.
>>>
>>> dog = Dog('dog') # 创建 dog 实例
>>> dog.greet()
WangWang.., I am dog.
我们还可以对
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s. ' % self.name
def run(self):
print 'I am running.I am running'
使用:
>>> dog = Dog('dog')
>>> dog.greet()
WangWang.., I am dog.
>>> dog.run()
I am running
多态
多态的概念其实不难理解,它是指对不同类型的变量进行相同的操作,它会根据对象(或类)类型的不同而表现出不同的行为。
class Animal(object):
def **init**(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
class Dog(Animal):
def greet(self):
print 'WangWang.., I am %s.' % self.name
class Cat(Animal):
def greet(self):
print 'MiaoMiao.., I am %s' % self.name
def hello(animal):
animal.greet()
看看多态的使用:
>>> dog = Dog('dog')
>>> hello(dog)
WangWang.., I am dog.
>>>
>>> cat = Cat('cat')
>>> hello(cat)
MiaoMiao.., I am cat
可以看到,cat
和 dog
是两个不同的对象,对它们调用 greet
方法,它们会自动调用实际类型的 greet
方法,作出不同的响应。这就是多态的魅力。
super
在类的继承中,如果重定义某个方法,该方法会覆盖父类的同名方法,但有时,我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可通过使用
class Animal(object):
def __init__(self, name):
self.name = name
def greet(self):
print 'Hello, I am %s.' % self.name
class Dog(Animal):
def greet(self):
super(Dog, self).greet() # Python3 可使用 super().greet()
print 'WangWang...'
在上面,greet
方法,为了能同时实现父类的功能,我们又调用了父类的方法,看下面的使用:
>>> dog = Dog('dog')
>>> dog.greet()
Hello, I am dog.
WangWang..
super
的一个最常见用法可以说是在子类中调用父类的初始化方法了,比如:
class Base(object):
def __init__(self, a, b):
self.a = a
self.b = b
class A(Base):
def __init__(self, a, b, c):
super(A, self).__init__(a, b) # Python3 可使用 super().__init__(a, b)
self.c = c
MRO 列表
事实上,对于你定义的每一个类,
>>> C.mro() # or C.__mro__ or C().__class__.mro()
[__main__.C, __main__.A, __main__.B, __main__.Base, object]
那这个
- 子类永远在父类前面
- 如果有多个父类,会根据它们在列表中的顺序被检查
- 如果对下一个类存在两个合法的选择,选择第一个父类
让我们看一个稍微复杂的例子,涉及到多重继承,代码如下:
class Base(object):
def __init__(self):
print "enter Base"
print "leave Base"
class A(Base):
def __init__(self):
print "enter A"
super(A, self).__init__()
print "leave A"
class B(Base):
def __init__(self):
print "enter B"
super(B, self).__init__()
print "leave B"
class C(A, B):
def __init__(self):
print "enter C"
super(C, self).__init__()
print "leave C"
其中,
Base
/ \
/ \
A B
\ /
\ /
C
现在,让我们看一下使用:
>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C
如果你认为 super
代表『调用父类的方法super
和父类没有实质性的关联。super
的工作原理如下:
def super(cls, inst):
mro = inst.__class__.mro()
return mro[mro.index(cls) + 1]
其中,
- 获取
inst 的MRO 列表 - 查找
cls 在当前MRO 列表中的index, 并返回它的下一个类,即mro[index + 1]
当你使用 super(cls, inst)
时,__init__
方法:
super(C, self).__init__()
这里的
[__main__.C, __main__.A, __main__.B, __main__.Base, object]
可以看到,__init__
,这时会打印出
super(A, self).__init__()
注意,这里的__init__
,这时会打印出