面向对象三大要素:封装,继承,多态,这其中有一个不会用就应该不算会用面向对象语言吧
前面我简单讲了一下封装,那么这一节要讲解继承
不过我想在讲解这个地方之前, 想先讨论一下,是否大家还记得C++的菱形问题
如果不记得,也无所谓,我只想说,虽然C++和python都支持多继承的问题,但是我们在这里不考虑多继承,因为多继承很有可能会造成很大的问题,没有必要去冒着风险学习多继承,所以我们还是就是认认真真把单继承学好就行(其实我是看了其他很多面向对象语言取消了多继承才这样说)
废话不多说,来看一下继承问题:
```
class people():
name= 'people'
age= '23'
def setname(self,name):
self.name= "people"+" "+name
def setage(self,age):
self.age= age
class person(people):
name= 'person'
def setname(self,name):
self.name= "person"+" "+name
a= person()
print(a.name)
a.setname("aaa")
a.setage(30)
print(a.name)
print(a.age)
people.setname(a,"qqq")#非绑定方法的调用
print(a.name)
输出结果:
person
person aaa
30
people qqq
```
我举这个例子,主要是为了说明大多数的情况,这里不考虑构造函数,私有继承这两块,我只说明的是普通的继承的情况
1、首先父类和子类名称还有方法不重名,可以看到,子类完全继承了父类
2、父类和子类出现了重名,可以看到重名的子类覆盖了父类
目前我们记住这两点就够了,后面还会再讲一下,对了,如果你一定要是用多继承如:
person(people,animal)这样,那么如果也出现重名的话,那么优先会使用排在前面的,当然,最好不这么用
但是文章写到这里之后,我突然想起一个问题,因为之前没有讲到什么是绑定方法调用,什么是非绑定方法调用
如果我们实例化一个类,通过对象调用这个方法,这是绑定方法的调用
如果是通过类来,然后把对象当做参数传进去,那么就是非绑定方法调用
如:
```
a = person()
a.setname("www")这就是绑定方法的
people.setname(a,“www”)这就是非绑定方法
```
通过非绑定方法,可以让被重写的父类的方法重新恢复了,这是我为啥一定要介绍这个
===============================================================
讲到这里,剩下还有几个点需要注意一下
1、私有成员(包括私有的属性+方法)是否可以继承,先看个例子:
```
class people():
name= 'people'
__age= '23'
def setname(self,name):
self.name= "people"+" "+name
def __funa(self):
print("wwww")
def funb(self):
self.__funa()
class person(people):
name= 'person'
def setname(self,name):
self.name= "person"+" "+name
@property
def age(self):
return self.__age
a= person()
a.funb()
print(a.age)#打印错误
报错:'person' object has no attribute '_person__age'
很清楚的说明了就是私有成员是没有办法继承的
第二点:super函数的使用,这个是相对于多继承才会使用:
class People:
def __init__(self,name):
self.name=name
def say(self):
print("我是人,名字为:",self.name)
class Animal:
def __init__(self,food):
self.food=food
def display(self):
print("我是动物,我吃",self.food)
class Person(People,Animal):
#自定义构造方法
def __init__(self,name,food):
#调用 People 类的构造方法
super().__init__(name)
#super(Person,self).__init__(name) #执行效果和上一行相同
#People.__init__(self,name)#使用未绑定方法调用 People 类构造方法
#调用其它父类的构造方法,需手动给 self 传值
Animal.__init__(self,food)
per=Person("zhangsan","熟食")
per.say()
per.display()
```
看到没,这是如果是多继承的话,存在一个问题,就是在继承的时候,优先选择第一个,然后就是那我们想两个父类的构造函数都可以使用,那么就自己在person的构造函数中,调用前两个父类的构造函数即可;其中super()函数代表的是第一个父类可以用绑定方法的方式来调用;但是对于第二父类也就是animal来说,就不行了;他只能是用非绑定的方法进行调用;可以看到第一个参数也是self,代表的是被person所继承,使用的对象是person创建出的对象;然后第二个参数是food,代表给从animal继承而来的food进行赋值;