多态
第一次接触多态,之前没有学习过java中关于多态到底是怎么说明的,听说java的多态和Python的很不一样,这里我只是说一下针对于Python方面我对多态的理解;
什么是多态呢?
顾名思义多态就是多种状态,多态使用的前提是继承以及方法重写;
我们知道Python中的变量定义是不需要指定类型的,只有在给它第一次赋值的时候它的类型才会随之确定,但也并不是之后就会保持一成不变,它随着引用对象的改变而改变,比如:
#定义变量 a = True,它的意思并不是 a 就是 True,a 只是 True 的一个引用
#我们可以定义许多变量,它们都可以是True的引用,当然在引用之后,它们的类型都是bool型
a = True
print(type(a)) #<class 'bool'>
#那么 a 从此之后就是 bool 型的了吗?当然不能这么说,我们可以让 a 成为其它数据的引用
a = [1,2,3,4]
print(type(a)) #<class 'list'>
# a又成为了list类型
这个例子与Python中的多态联系不大,只是作为一个引子;
接下来进入正题:
在学类和对象时我们学到了继承,接下来随便写一个例子:
class Animal():
def __init__(self,name):
self.name = name
def running(self):
print(self.name.title() + " is running.")
class Cat(Animal):
pass
class Dog(Animal):
pass
如上有三个类,其中Cat和Dog都继承自Animal,那么想一想,Cat和Dog的数据类型可以是Animal吗?
c = Cat('Tom')
print(isinstance(c,Cat)) # True
print(isinstance(c,Animal)) #True
可以看到,子类Cat既是Cat类型,又是Animal类型,这就有点意思了,但真正有意思的还不止于此:
class Animal():
def __init__(self,name):
self.name = name
def running(self):
print(self.name.title() + " is running.")
class Cat(Animal):
pass
class Dog(Animal):
pass
class Bird(Animal):
def flying(self):
print(self.name.title() + " is flying.")
def text(obj):
obj.running()
在这段代码中,我定义了一个父类、三个子类和一个函数,这个函数传入一个参数,运行它的running方法;
c = Cat('Tom')
d = Dog('Acai')
b = Bird('Pink')
text(c)
text(d)
text(b)
##
Tom is running.
Acai is running.
Pink is running.
可以看到,Cat对象、Dog对象、Bird对象都成功执行了text函数,虽然Bird对象并没有执行我们期望的flying方法,但那是因为我们的函数写的是执行running方法的缘故;
可是为什么这些对象都能成功执行text()函数,并调用出了Animal对象中的running方法呢?
你可能会认为因为它们都继承自Animal,它们也都属于Animal类型,但事实上,我们不妨再看一个例子:
class Animal():
def __init__(self,name):
self.name = name
def running(self):
print(self.name.title() + " is running.")
class Dog(Animal):
pass
class Smalldog(Dog):
pass
class Cat():
def __init__(self,name):
self.name = name
def running(self):
print(self.name.title() + " is running.")
def text(obj):
obj.running()
sd = Smalldog('jack')
c = Cat('biubiu')
text(sd)
text(c)
##
Jack is running.
Biubiu is running.
在这个例子中,第一个证明了子类的子类依然能够成功执行text函数,使用running方法,但第二个呢?这次的Cat对象不是任何类的子类。
这时你就会发现所有这些都有一个通性,即它们都有running方法,事实上text传入的参数是obj,它本来就是不明确类型的,而text函数又用到了obj的running方法,那么Python就会依次作为判断依据,只要传入的对象含有running方法,那么它就是合法的,如果没有那就报错;
这就是Python作为动态语言的一个显著特点----鸭子类型;即一个对象“只要看起来像鸭子,走起路来也像”,那么它就可以看作鸭子;
对于上文的text函数来说,它要传入的就是一只鸭子,而只要含有running方法的任何对象,Python都会把它当作鸭子看待,而不要求传入的必须是父类或者子类这种严格规定;