zoukankan      html  css  js  c++  java
  • 继承、抽象类、多继承

    # 继承的引子
    # 假设我们现在有一个游戏,游戏中有这些具体的事物(对象 ): 梅西、奥巴马、史努比、史派克、小猪配齐、猪八戒。
    # 采取面向对象设计的方法,是要对游戏中的具体对象,进行分门别类的抽象,抽取中相似对象的共同特征和行为来,作为一种规范,
    # 一种模板来,梅西和奥巴马,它们的相似,具有人的特征,因此,我们把它们归为一类,即人类,就抽象出人类这一概念来了。
    # 史努力和史派克 具有共同的特征和行为,我们把它们归为一类,并取名为狗类,完成具体到综合的第一次抽象,而小猪配齐和希猪八戒,
    # 它们两个具体的事物,又具有共性的东西,因此将它们归为一类,并取名为猪类。
    # 以上,通过对抽取相似具体事物的共同特征,归为一类,完成了事物的第一层抽象。
    # 梅西、奥巴马、史努比、史派克、小猪配齐、猪八戒 ===》 人类 、狗类 、 猪类 # 基本的分类
    # 人类 、狗类 、 猪类 ===》 经过再一次抽象,抽象出 动物类。
    # 因此面向对象的过程,就是由具体 到 抽象 的过程。从宏观上,概念上 统领相似事物。抽象的层次,越高,能够描述和规范的事物就越多。
    # # 猫类:
    # 属性: 名字,品种,食物
    # 方法: 叫,抓老鼠,吃,喝
    # 狗类:
    # 属性: 名字,品种,食物
    # 方法:叫,看家,吃,喝
    # 人类:
    # 属性:名字,品种,食物
    # 方法:说话,工作,吃,喝
    # 虽然,我们从具体的事物,抽象出三个类别,但是我们发现,这三类之间,还有共同的代码,没有提高代码的重用性。
    # 于是乎,我们可以将三个类别的共同代码,再抽取出来,建立一个类别,比如说叫动物类,它让猫类、狗类、人类隶属于这个类,
    # 也就具有这个类的属性。
    # 那么用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")
    pass

    s1 = 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 装饰器装饰的方法
  • 相关阅读:
    多重背包POJ1276不要求恰好装满 poj1014多重背包恰好装满
    哈理工1053完全背包
    求最小公倍数与最大公约数的函数
    Bus Pass ZOJ 2913 BFS 最大中取最小的
    POJ 3624 charm bracelet 01背包 不要求装满
    HavelHakimi定理(判断一个序列是否可图)
    z0j1008Gnome Tetravex
    ZOJ 1136 Multiple BFS 取模 POJ 1465
    01背包 擎天柱 恰好装满 zjut(浙江工业大学OJ) 1355
    zoj 2412 水田灌溉,求连通分支个数
  • 原文地址:https://www.cnblogs.com/chris-jia/p/9557264.html
Copyright © 2011-2022 走看看