继承、抽象类、多继承

# 继承的引子# 假设咱们如今有一个游戏,游戏中有这些具体的事物(对象 ): 梅西、奥巴马、史努比、史派克、小猪配齐、猪八戒。# 采起面向对象设计的方法,是要对游戏中的具体对象,进行分门别类的抽象,抽取中类似对象的共同特征和行为来,做为一种规范,# 一种模板来,梅西和奥巴马,它们的类似,具备人的特征,所以,咱们把它们归为一类,即人类,就抽象出人类这一律念来了。# 史努力和史派克 具备共同的特征和行为,咱们把它们归为一类,并取名为狗类,完成具体到综合的第一次抽象,而小猪配齐和希猪八戒,# 它们两个具体的事物,又具备共性的东西,所以将它们归为一类,并取名为猪类。# 以上,经过对抽取类似具体事物的共同特征,归为一类,完成了事物的第一层抽象。#  梅西、奥巴马、史努比、史派克、小猪配齐、猪八戒 ===》  人类 、狗类 、 猪类  # 基本的分类#  人类 、狗类 、 猪类 ===》 通过再一次抽象,抽象出 动物类。# 所以面向对象的过程,就是由具体  到 抽象 的过程。从宏观上,概念上 统领类似事物。抽象的层次,越高,可以描述和规范的事物就越多。# # 猫类:#     属性: 名字,品种,食物#     方法: 叫,抓老鼠,吃,喝# 狗类:#     属性: 名字,品种,食物#     方法:叫,看家,吃,喝# 人类:#     属性:名字,品种,食物#     方法:说话,工做,吃,喝# 虽然,咱们从具体的事物,抽象出三个类别,可是咱们发现,这三类之间,还有共同的代码,没有提升代码的重用性。# 因而乎,咱们能够将三个类别的共同代码,再抽取出来,创建一个类别,好比说叫动物类,它让猫类、狗类、人类隶属于这个类,# 也就具备这个类的属性。# 那么用puthon代码如何实现呢?# 定义 一个 Animal() 的父类class Animal:    # 父类,超类,基类    def __init__(self,name,kind,food,language):        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):   # 派生类    def catch_mouse(self):        print("抓老鼠")class Dog(Animal):  # 派生类    def __init__(self,name,kind,food,language,eye_color):  # 子类重写父类的方法,并经过super()方法,调用父类的同名方法        self.eye_color = eye_color                          # 派生属性        super().__init__(name,kind,food,language) # self ,不用传,会自动传    def swim(self):            # 派生方法        print("游泳")    def look_afte_home(self):        print("看家")class Human(Animal):  # 派生类    def __init__(self):               # 这里子类对父类的方法,进行了重写,即覆盖了父类,此时父类的同名方法,对子类就不可见了。        self.walk_way = "直立行走"    def work(self):        print("工做")# 在继承关系中,被继承的类,咱们称之为超类/基类/父类, : 好比上面的 Animal类# 继承的类,叫作子类/派生类: 好比上面的 Cat, Dog, Person# 继承与重用:是同一个事物的两方面,类的继承就是了为提升代码的重用性,提升代码的重用性,除了函数,类就是别外一种的实现方式。# 好比说:写了两个类或多个类,它们有共同的代码或逻辑,这时候就能够为它们建立一个父类,把共同的代码或逻辑放到父类里,这时经过继承# 就实现了代码的重用性。# 继承与重用,父类中的全部方法和属性都被子类中使用了。阿猫 = Cat("阿猫","花猫","鱼","喵喵")阿猫.yell()阿猫.eat()阿猫.drink()print(阿猫.name)yellDog = Dog("黄狗","土狗","骨头","汪汪","蓝色")yellDog.eat()yellDog.drink()yellDog.yell()print(yellDog.name)xiaomin = Human()                   # 由于子类对父类的 __init__方法,进行了重写,除了self之外,没有参数,不须要手动传参。print(xiaomin.walk_way)yellDog.swim()# 总结:当子类当中有要被调用的方法 和 属性的时候,子类的对象会直接选择子类中的方法、变量,父类中的同名方法不会被自动执行。# 若是咱们既想要执行子类中方法,也想要执行父类中的同名方法,那么须要在子类的方法中调用父类的方法:有两种方式:# 父类名.方法名(...)# super().方法名(...)# 面试题:class Foo:    def __init__(self):  # 初始化对象实例的函数,此函数仅在调用 类名() 时执行一次        self.func()     # 对象调用    def func(self):        print('in Foo')class Son(Foo):    # def func(self):    #     print("in Son")    passs1 = Son()      # 建立了一个Son类的对象实例,并赋值给对象引用 s1。过程是,在内存中开辟一个对象空间,根据对象所属的直接类的类#对象指针 找寻 __init__方法执行,子类没有,在父类中寻找,找到将对象传递参数self,执行 __init__函数体,执行self.func()语句,# 对象执行一个方法,先在对象所属直接类中,找到,直接执行,没有找到,再到父类找,因此此处是打印 in 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'# 结论:始终注意,那个对象调用 ,self就是哪一个对象# 抽象类# 工做中 公司使用抽象类 ,来规范 开发的规则。# 源码 别人使用抽象类from abc import ABCMeta,abstractmethod   # 从 abc 这个外部模块中,导入 ABCMeta 类 和 abstracmethod这个用于装饰函数的装饰器class Payment(metaclass=ABCMeta):  # 给类的元类,传递一个关键字参数    @abstractmethod    def pay(self):pass    # 抽象方法,仅有定义,没有方法的实现    @abstractmethod    def shouqian(self):pass            # 假如,把这两行的注释打开,若是子类不实现这个方法,程序会报错                                    #    a = Alipay()                                       # TypeError: Can't instantiate abstract class Alipay with abstract methods shouqian    def abstract(self):        print("我继承抽象类")class Alipay(Payment):    def pay(self,money):        print("使用支付宝支会了%s元" % money)    def shouqian(self,money):        print("使用收款方式收到%s元" % money)class Wechatpay(Payment):    def pay(self,money):        print("使用微信支付了%s元" % money)    def shouqian(self,money):        print("使用收款方式收到%s元" % money)class Applepay(Payment):    def pay(self,money):        print("使用applepay支付了%s元" % money)    def shouqian(self,money):        print("使用收款方式收到%s元" % money)# def pay(obj,money):#     obj.pay(money)a = Alipay()a.pay(100)a.shouqian(2000)a.abstract()     # 抽象类,也能够有普通方法,子类继承wechat = Wechatpay()wechat.pay(260)wechat.shouqian(489)apple = Applepay()apple.pay(159)apple.shouqian(6000)# 以上多个子类,继承同一个抽象类,子类必须去实现抽象类中用@abstractmethod装饰器装饰的方法,不然会报错。# 实现了不一样的对象,调用相同的方法# 在上面的基础上,咱们来定义 一个 统一的函数,也能够叫接口def 付钱(obj,money):    obj.pay(money)#  这样,func()就是一个统一的支付接口付钱(wechat,1600)付钱(a,3500)def 收钱(obj,money):    obj.shouqian(money)收钱(a,10000)收钱(apple,30000)# p = Payment()    # 抽象类 , 不能实例化 TypeError: Can't instantiate abstract class Payment with abstract methods pay, shouqian# 总结: 抽象类 是一种 规范#  多人开发、复杂的需求、后期的扩展# 手段,来帮助咱们完成规范。# 抽象类 如何建立#  抽象类是一个规范,它基本上不会实现什么具体的功能,抽象类是不能被实例化的。# 要想写一个抽象类的步骤:#   from abc  import ABCMeta,abstractmethod#   在建立这个类的时候,指定 metaclass = ABCMeta#   在你但愿子类实现的方法上加一个 @abstractmethond 装饰器#  使用抽象类:#   继承这个类#   必须实现这个类中被 @abstractmehond 装饰器装饰的方法
相关文章
相关标签/搜索