- 当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
[组合是"有"的关系,继承是"是"的关系] --->比如教授有生日,比如白马是马,人是动物
1
继承
- 继承与抽象(先抽象再继承)
- 抽象即抽取类似或者说比较像的部分。
- 父类/超类/基类
- 子类/派生类
- 继承与重用 - 父类中所有的属性和方法都可以被子类使用
- 子类调用属性和方法找不到会去父类去找------>继承
派生
- 当子类当中有要被调用的方法的时候,子类的对象会直接选择子类中的方法、变量,父类中的方法不会被自动执行
- 如果我们既想要执行子类的方法,也想要执行父类的方法,那么需要在子类的方法中调用父类的方法[重点]:
- 父类名.方法名(self,...) [用法同下]
- super().方法名(...)
- 帮助我们在子类中调用父类中的同名方法
class Animal:
def __init__(self,name,kind,food,language):
print('in animal')
self.name = name
self.kind = kind
self.food = food
self.language = language
def yell(self):
print('%s叫'%self.language)
def eat(self):
print('吃%s'%(self.food))
def drink(self):
print('喝水')
class Cat(Animal): # Animal的派生类
def __init__(self,name,kind,food,language,eye_color):
print('in Cat')
self.eye_color = eye_color # 派生属性
# Animal.__init__(self,name,kind,food,language)
super().__init__(name,kind,food,language)
def catch_mouse(self): # 派生方法
print('抓老鼠')
def eat(self): # 不仅执行了父类中的基础功能,还完成了特殊的功能
Animal.eat(self)
# super().eat()
self.weight = 10
class Dog(Animal):
def look_after_house(self):
print('看家')
def eat(self):
# Animal.eat(self)
super().eat()
self.drink()
阿猫 = Cat('阿猫','橘猫','牛杂','喵喵','绿色')
print(阿猫.eye_color)
print(阿猫.food)
阿猫.catch_mouse()
阿猫.eat()
print(阿猫.weight)
2
面试题
class Foo:
def __init__(self):
self.func()
def func(self):
print('in Foo')
class Son(Foo):
def func(self):
print('in Son')
s1 = Son()
class Foo:
Country = 'China'
def func(self):
print(self.Country)
class Son(Foo):
Country = 'English'
def func(self): # 走这个方法
print(self.Country)
s = Son()
s.func()
class Foo:
Country = 'China'
def func(self): # 走这个方法
print(self.Country)
class Son(Foo):
Country = 'English'
s = Son()
s.func() # English
class Foo:
Country = 'China'
def func(self):
print(self.Country)
class Son(Foo):pass
s = Son()
s.func() # 'China
运行结果:
in Son
English
English
China
Process finished with exit code 0
3
抽象类
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta): # 模板的功能
@abstractmethod # abstractmethod是一个装饰器,装饰器怎么用?放在函数/类的上一行
def pay(self):pass
@abstractmethod
def shouqian(self):pass
规范
多人开发、复杂的需求、后期的扩展
手段 来帮助我们完成规范
-
抽象类
抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的
从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。
抽象类就是从一堆类中抽取相同的内容而来的
python也有抽象类的概念但是同样需要借助模块实现.
抽象类是一个规范,它基本不会实现什么具体的功能,抽象类是不能被实例化- 要想写一个抽象类
- from abc import ABCMeta,abstractmethod
- 在这个类创建的时候指定 metaclass = ABCMeta
- 在你希望子类实现的方法上加上一个 @abstractmethod装饰器
- 使用抽象类
- 继承这个类
- 必须实现这个类中被@abstractmethod装饰器装饰的方法
- 要想写一个抽象类
4
多继承
子类继承父类逻辑上要行得通
父类的属性和方法属于子类
多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
# 天鹅 飞 游泳 走路
# 老虎 走路 游泳
# 鹦鹉 飞 说话 走路
class Animal:
def __init__(self,name):
self.name = name
class FlyAnimal(Animal):
def fly(self):
print('%s在飞' % self.name)
class WalkAnimal(Animal):
def walk(self):
print('%s在走路'%self.name)
class SwimAnimal(Animal):
def swim(self):
print('%s在游泳'%self.name)
class Tiger(SwimAnimal,WalkAnimal):
pass
class Swan(SwimAnimal,WalkAnimal,FlyAnimal):
pass
class Parrot(FlyAnimal,WalkAnimal):
def talk(self):
print('%s说话了'%self.name)
swan = Swan('天鹅')
swan.fly()
swan.walk()
5
接口类
抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计
在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念
抽象类的本质还是类,指的是一组类的相似性
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
java c#
不允许多继承
接口 Interface 接口可以被多继承
Interface FlyAnimal: # 规范继承我的类必须实现这个方法
def fly():pass
class Tiger(WalkAnimal,SwimAnimal): 继承了一个规范
def walk():代码
def swim():代码
6
钻石继承
bases则是查看所有继承的父类
base只查看类的第一个父类
新式类
在python3.x版本中 所有的类都是新式类
所有的新式类都有一个默认的父类 : object-
在新式类中
- 所有的多继承关系寻找方法的顺序 - 遵循广度优先算法
- 继承object
- mro方法:查找父类顺序 F.mro() #等同于F.__mro__
- super : super不是单纯的找父类,而是遵循mro顺序的
3种写法都一样
class Person1:pass
class Person2():pass
class Person3(object):pass
- 多继承的顺序
- D,B,C,A
class A:
def func(self):
print('A')
class B(A):
pass
# def func(self):
# print('B')
class C(A):
pass
# def func(self):
# print('C')
class D(B,C):
pass
# def func(self):
# print('D')
print(D.mro())
d = D()
d.func()
class A:
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(A):
def func(self):
super().func()
print('C')
class D(B,C):
def func(self):
super().func()
print('D')
D().func()
B().func()
结果
A
C
B
D
A
B
Process finished with exit code 0
python 2.7
- 经典类
python2.x
不主动继承object
经典类在找父类中方法的过程中, 遵循 —— 深度优先
不提供mro方法和super
经典类 和 新式类 并存
class Student:pass # 经典类
class Student(object):pass#新式类
总结:继承了object的类就是新式类