继承和接口与归一化设计
继承和接口与归一化设计
继承
继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或多个父类,原始类被称为基类或超类,新建的类被称为派生类或子类。
class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1(ParentClass1): #单继承,基类是ParentClass1,派生类是SubClass pass class SubClass2(ParentClass1,ParentClass2): #python支持多继承,用逗号分隔开多个继承的类 pass print(ParentClass1.__bases__) print(SubClass1.__bases__) print(SubClass2.__bases__)
继承与抽象
抽象即是抽取类似或者比较像的部分,抽象分为两个层次。
1、将奥巴马和梅西这俩对象比较像的部分抽取成类。
2、将人、猪、狗这三个类比较像的部分抽取成父类
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
继承是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
class Aniaml: def __init__(self,name,age): self.name = name self.age = age def walk(self): print('%s is walking' %self.name) def say(self): print('%s is saying' %self.name) class People(Aniaml): pass class Pig(Aniaml): pass class Dog(Aniaml): pass p1 = People('obama',50) #people没有name和age,但是people继承了animal,所以可以使用animal的name和age print(p1.name) print(p1.age) p1.walk()
继承可以解决重用性。
上面的例子就说明了重用性,在people类中,不用再写walk和say,在继承的父类animal中调用即可。
派生
派生就是将类共有的属性(特征)和函数(技能)单独取出,作为一个父类后,子类里在添加的属性和函数,就是派生。派生出类自己的东西。
class Hero: def __init__(self, nickname,aggressivity,life_value): self.nickname = nickname self.aggressivity = aggressivity self.life_value = life_value def attack(self, enemy): print('Hero attack') class Garen(Hero): camp = 'Demacia' def attack(self, enemy): #self=g1,enemy=r1 # self.attack(enemy) #g1.attack() Hero.attack(self,enemy) #用父类里的attack,参数是Hero里的attack的参数。这里的self是g1,enemy是r1 print('from garen attack') def fire(self): print('%s is firing' % self.nickname) class Riven(Hero): camp = 'Noxus' g1 = Garen('garen', 18, 200) r1 = Riven('rivren', 18, 200) g1.attack(r1) print(g1.camp) print(r1.camp) g1.fire()
组合
组合是类与类之间有的关系, 当类之间有着明显不同,并且较小的类是较大的类所需要的组件时,用组合比较好。
接口与归一化设计
在python中,没有接口的概念。而接口的概念,简单的说就是对外的入口。所以在python中,要实现接口的效果,只能用继承去模拟。
在继承中,父类不用去实现具体的功能,而是在子类中,具体的去实现。
class Interface:#定义接口Interface类来模仿接口的概念,python中压根就没有interface关键字来定义一个接口。 def read(self): #定接口函数read pass def write(self): #定义接口函数write pass class Txt(Interface): #文本,具体实现read和write def read(self): print('文本数据的读取方法') def write(self): print('文本数据的写入方法') class Sata(Interface): #磁盘,具体实现read和write def read(self): print('硬盘数据的读取方法') def write(self): print('硬盘数据的写入方法') class Process(Interface): def read(self): print('进程数据的读取方法') def write(self): print('进程数据的写入方法') t1=Txt() s1=Sata() p1=Process() t1.read() t1.write() s1.read() s1.write() p1.read() p1.write()
抽象
import abc #抽象类:本质还是类,与普通类额外的特点的是:加了装饰器的函数,子类必须实现他们 class Animal(metaclass=abc.ABCMeta): tag='123123123123123' @abc.abstractmethod def run(self): pass @abc.abstractmethod def speak(self): pass class People(Animal): def run(self): pass def speak(self): pass peo1=People() print(peo1.tag)
继承的顺序
继承的顺序分为python2和python3。
在python2中,经典类和新式类的继承方式是不同的。
py2中,经典类的多继承顺序是:优先深度查找。新式类的多继承顺序是:优先广度查找。
在py3中,只有新式类,所以py3只有广度优先查找。
新式类:
#新式类的继承,在查找属性时遵循:广度优先 class A(object): def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): def test(self): print('from F') f1=F() f1.test() print(F.__mro__) print(F.mro()) #广度优先:F->D->B->E->C->A->object
经典类:
#python2中经典类的继承,在查找属性时遵循:深度优先 class A: number = 10 def test(self): print('from A') class B(A): def test(self): print('from B') class C(A): def test(self): print('from C') class D(B): def test(self): print('from D') class E(C): def test(self): print('from E') class F(D,E): def test(self): print('from F') f1=F() f1.test() print(f1.number) ###F->D->B->A->E->C
super函数
子类调用父类的方法,用super方法。
除了在子类中,用类名.的方法调用父类方法外,还可以用super方法。
#在python3中 class People: def __init__(self,name,sex,age): self.name=name self.age=age self.sex=sex def walk(self): print('%s is walking' %self.name) class Chinese(People): country='China' def __init__(self,name,sex,age,language='Chinese'): # self.name=name # self.sex=sex # self.age=age # People.__init__(self,name,sex,age) super(Chinese,self).__init__(name,sex,age) #super()相当于一个对象,super().__init__相当于是调用对象的绑定方法。也就是调用父类的绑定方法。 self.language=language def walk(self,x): super().walk() print('子类的x',x) c=Chinese('egon','male',18) print(c.name,c.age,c.sex,c.language) c.walk(123)
---------- END ---------