面向对象中的继承

面向对象中的三大特性(所有语言通用)

继承

多态

封装


继承的目的:为了解决类与类之间代码重复的问题

类的继承的语法:
单继承
class A:pass
class B(A):pass
print(B.__bases__)
在定义类的时候加(),括号写的类就是继承的类
B类继承A类
A类 : 父类 基类 超类
B类 : 子类 派生类
多继承(python支持 java不支持)
class C:pass
class D:pass
class E(C,D):pass
print(E.__bases__)
E继承C,D
C,D都是父类
E是子类
 
使用继承这个概念的过程
class Animal:
def __init__(self,name,kind,language):
self.name = name
self.kind = kind
self.language = language
def eat(self):
print('%s is eating'%self.name)
def drink(self):
print('%s is drinking'%self.name)
def yell(self):
print('%s say %s'%(self.name,self.language))
class Cat(Animal):pass
class Dog(Animal):pass
小花 = Cat('小花','金吉拉','喵喵')
小黑 = Dog('小黑','土狗','旺旺')
小花.yell()
小黑.yell()
print(小花.name)
print(小花.kind)
子类可以继承父类的方法和属性
实例化的执行流程:
先开辟一块空间,并且空间中已经有了一个类指针,指向Cat
执行__init__方法,在Cat类的空间中没有init方法,找Animal类中的init
将空间返回给小花变量
继承
子类调用方法,如果子类自己有用自己的,用了自己的就不用父类的了
如果子类自己没有才调用父类的

对于有不同的方法
class Animal:
def __init__(self,name,kind,language):
self.name = name
self.kind = kind
self.language = language
def eat(self):
print('%s is eating'%self.name)
def drink(self):
print('%s is drinking'%self.name)
def yell(self):
print('%s say %s'%(self.name,self.language))
class Cat(Animal):
def climb(self): # 派生方法
print('%s can climb'%self.name)
class Dog(Animal): # 派生方法
def lookafter_door(self):
print('%s can look after door'%self.name)
小花 = Cat('小花','金吉拉','喵喵')
小黑 = Dog('小黑','土狗','旺旺')
小花.climb()
小黑.lookafter_door()

animal_1 = Animal('大金鱼','鱼','吐泡泡')
animal_1.climb() # 报错

继承

子类调用方法,如果子类自己有用自己的,用了自己的就不用父类的了
如果子类自己没有才调用父类的
如果子类有个性化的父类没有的方法,可以单独定义在子类中 - 派生方法
只有子类能够使用父类中的方法,父类不可以使用子类中的方法
具体的例子:


class Animal:
def __init__(self,name,kind,language):
self.name = name
self.kind = kind
self.language = language
def eat(self):
print('%s is eating'%self.name)
def drink(self):
print('%s is drinking'%self.name)
def yell(self):
print('%s say %s'%(self.name,self.language))
def sleep(self):
print('%s 在睡觉'%self.name)
class Cat(Animal):
def climb(self): # 派生方法
print('%s can climb'%self.name)
def sleep(self):
#1. Animal.sleep(self) # 父类名,主动传self
#super(self,Cat).sleep() # 过程 super(self,子类名).方法名()
#2. super().sleep() # super().方法名()
print('团着睡')
class Dog(Animal): # 派生方法
def lookafter_door(self):
print('%s can look after door'%self.name)

小花 = Cat('小花','金吉拉','喵喵')
小花.sleep() # 既希望走父类的基础的sleep,又希望走自己的方法

当某一个方法,父类和子类都拥有的时候,那么在子类的方法中,调用父类的同名方法
1.父类名.方法名(self,...)
2.super().sleep(...)

 
总结:
继承
两种语法:
单继承
多继承
几个基础概念
父类 : 超类 基类
子类 : 派生类
为什么要继承 : 几个类之间有重复的属性/方法 ,就把相同的属性和方法抽象出来,作为父类,子类去继承父类
父类和子类之间的关系 : 子类关联父类,父类并不关联子类
子类使用父类的方法
子类中有,父类中没有 : 用子类的
父类中有,子类中没有 : 用父类的
子类\父类中都有 : 默认情况下用子类的不用父类的
既想用父类又想用子类 : 父类名.方法名(子类对象),super().方法名()
子类\父类中都没有 : 报错


抽象类: from abc import ABCMeta,abstractmethod
举例说明:
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod #规定支付功能
def pay(self):pass

@abstractmethod #规定退款功能
def back(self): pass

class AliPay(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过支付宝消费了%s元'%(self.name,money))
def back(self,tk):
print('%s通过支付宝退款了%s元'%(self.name,tk))

class WeChatPay(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过微信消费了%s元'%(self.name,money))
def back(self,tk):
print('%s通过微信退款%s元'%(self.name,tk))

class ApplePay(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过苹果消费了%s元'%(self.name,money))
def back(self,tk):
print('%s通过苹果退款%s元'%(self.name,tk))

def pay_func(person,payway,money,tk):
if payway == 'alipay':
per = AliPay(person)
elif payway == 'wechatpay':
per = WeChatPay(person)
elif payway == 'applepay':
per = ApplePay(person)
per.pay(money)
per.back(tk)

pay_func('张飞','alipay',200,100)
pay_func('关羽','wechatpay',300,100)
pay_func('刘备','applepay',4200,100)主要是解决同事协作之间的代码规范问题
规定:(上例中)Payment 就是一个规范类,这个类存在的意义不在于实现实际的功能,而是为了约束所有的子类必须实现pay的方法
Payment : 抽象类
pay = Payment() # 抽象类: 不能实例化
抽象类主要就是作为基类/父类,来约束子类中必须实现的某些方法
抽象类的特点:
     from abc import ABCMeta,abstractmethod
        必须在类定义的时候指定metaclass = ABCMeta
必须在要约束的方法上方加上@abstractmethod方法
粗略使用:
from abc import ABCMeta,abstractmethod #(抽象方法)
class Payment(metaclass=ABCMeta): # metaclass 元类 metaclass = ABCMeta表示Payment类是一个规范类
@abstractmethod # @abstractmethod表示下面一行中的pay方法是一个必须在子类中实现的方法
def pay(self):pass

@abstractmethod
def back(self):pass # 退款功能

class ApplePay(Payment):
def pay(self):
pass
def back(self):
pass

接口类:
java 不支持多继承
python 支持多继承 :通过抽象类的多继承来实现复杂的规范
不同动物的相同行为是不能混为一谈
不同动物的相同行为的方法名字是必须一样

python
抽象类 : 抽象类中的方法可以写一些具体的py代码(规范)
单继承
多继承

java
不支持多继承,新的概念 接口 Interface
和抽象类几乎一模一样的功能 :
只定义一个接口名字(基类名),内部定义子类必须实现的方法
接口支持多继承
接口内部的所有方法都不能写具体的代码,只能用pass代替

抽象类 :
单继承的形容,并且在单继承中可以在方法中写python代码
接口类 : 更接近java中的接口的概念
python中由于有了抽象类的多继承,不需要接口的概念了
一个基类写出来被子类多继承了 : 接口类
并且在方法中只写pass(你可以选择性的满足)

 

案例说明
动物园
天鹅 : 飞 走 游泳
老虎 : 走 游泳
鹦鹉 : 飞 走 说话
from abc import ABCMeta,abstractmethod
class Fly_Animal(metaclass=ABCMeta):
@abstractmethod
def fly(self):
print('爷会飞')
class Swim_Animal(metaclass=ABCMeta):
@abstractmethod
def swim(self): pass
class Walk_Animal(metaclass=ABCMeta):
@abstractmethod
def walk(self): pass

class Swan(Fly_Animal,Swim_Animal,Walk_Animal):
def fly(self):
super().fly()
print('飞')
def walk(self):print('走')
def swim(self):print('游')

class Tiger(Walk_Animal,Swim_Animal):
def walk(self):print('走')
def swim(self):print('游')

class Parrot(Fly_Animal,Walk_Animal):
def fly(self):print('飞')
def walk(self):print('走')
def talk(self):print('说')

多继承:
python2 :两种类
python3 :只有一种类
新式类 : 默认继承object类 # object 是所有类的父类
为什么可以不写__init__?
所有object中的类都是你自己不写也可以调用的
区别
钻石继承问题/多继承的优先级问题
在python3中 所有的类都是新式类,所有的新式类的继承顺序都遵循C3算法,也叫广度优先算法
可以使用类名.__mro__()这个方法来查看这个继承顺序


案例说明:
class A:
pass
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):
pass
def func(self):print('D')

class E(C):
pass
def func(self):print('E')

class F(D,E):
pass
# def func(self):print('F')
f= F()
f.func()



C3算法 - 钻石模型
每一个类的继承顺醋都是从基类向子类看
形成一个指向关系的顺序[当前类]+[父类的继承顺序]
进行一个提取
如果一个类出现在从左到右的第一个顺序上
并且没有出现在后面顺序中
或者出现在后面的顺序中了但是仍然是第一个,
那么就把这个类提取出来
L(A) = [A] + [O]
A = [O]
L(A) = AO

L(B) = [B] + [AO]
B = [AO]
BA = [O]
L(B) = [BAO]

L(C) = [C] + [AO]
C = [AO]
CA = [O]
L[C] = [CAO]

L[D] = [D] + [BAO] + [CAO]
D = [BAO] + [CAO]
DB = [AO] + [CAO]
DBC = [AO] + [AO]
DBCA = [O] + [O]
L[D] = DBCAO


 
 
 


猜你喜欢

转载自www.cnblogs.com/Godisgirl/p/10004580.html