zoukankan      html  css  js  c++  java
  • 组合和多态(继承父类,抽象类,鸭子类型)

    组合

    1.什么是组合

    ​ 组合指的是某一个对象拥有一个属性,该属性的值是另外一个类的对象

     class Foo:
            pass
        class Bar:
            pass
        obj=Foo()
        obj.attr=Bar()
    
        obj.xxx
        obj.attr.yyy
    

    2. 为何要用组合

    通过为某一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合到一起,从而减少类与类之间代码冗余
    
     class Foo1:
            pass
        class Foo2:
            pass
        class Foo3:
            pass
    
        class Bar:
            pass
    
        obj_from_bar=Bar()
    
        obj1=Foo1()
        obj2=Foo2()
        obj3=Foo3()
    
        obj1.attr1=obj_from_bar
        obj2.attr2=obj_from_bar
        obj3.attr3=obj_from_bar
    

    3.组合使用场景

    组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同,
    1.继承的方式
    通过继承建立了派生类与基类之间的关系,它是一种'是'的关系,比如白马是马,人是动物。
    当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生是人
    
    2.组合的方式
    用组合的方式建立了类与组合的类之间的关系,它是一种‘有’的关系,比如教授有生日,教授教python和linux课程,教授有学生s1、s2、s3...
    当类之间有显著不同,并且较小的类是较大的类所需要的组件时,用组合比较好
    

    4 .组合使用示例

    class People:
        school = 'Oldboy'
    
        def __init__(self,name,age,sex,):
            self.name = name
            self.age = age
            self.sex = sex
    
    class Student(People):
        def __init__(self, name, age, sex,score=0):
            People.__init__(self,name,age,sex)
            self.score = score
    
        def choose_course(self):
            print('%s choosing course' % self.name)
    
    class Teacher(People):
        def __init__(self,name,age,sex,level):
            People.__init__(self,name,age,sex)
            self.level=level
    
        def score(self,stu,num):
            stu.score=num
    
    class Course:
        def __init__(self,c_name,c_price,c_period):
            self.c_name = c_name
            self.c_price = c_price
            self.c_period = c_period
    
        def tell_info(self):
            print('<课程名:%s 价钱:%s 周期:%s>' %(self.c_name,self.c_price,self.c_period))
    
    # 创建课程对象
    python=Course('python全栈开发',1900,'5mons')
    linux=Course('linux架构师',900,'3mons')
    
    stu1=Student('刘二蛋',38,'male')
    stu1.course=python
    # print(stu1.__dict__)
    stu1.course.tell_info()
    
    tea1=Teacher('zhang',18,'male',10)
    tea1.course=python
    # print(tea1.__dict__)
    tea1.course.tell_info()
    

    多态

    1.多态的定义:

    ​ 多态指的是同一种事物的多种形态

    2.多态的目的:

    ​ 多态也称之为多态性,在程序中继承就是多态的表现形式。
    ​ 多态的目的是为了让多种不同类型的对象,在使用相同的功能(方法)的情况下,都 能做出不同的响应。
    ​ 父类:定义一套统一的标准,
    ​ 子类:遵循父类统一的标准。
    ​ 多态的最终目的:统一子类编写规范,为了让使用者更方便调用相同功能的方法。而 多态的精髓就在于统一。

    3.如何实现多态

    1.继承父类

    class Animal:  # 父类定义一套统一的标准,不是为了实现某一具体功能,具体实现功能还是要继承的那些子类,这样使用者只需要学习父类的一套标准就行了。
        def eat(self):
            pass
        def drink(self):
            pass
        def speak(self):
            pass
            # print('我们一起喵喵喵。。。。')
    
    # 猪
    class Pig(Animal):
        # 吃
        def eat(self):
            print('猪在吃饭')
            pass
        # 喝
        def drink(self):
            pass
        def speak(self):
             # super().speak()
            print('哼哼哼~~~')
    # 猫
    class Cat(Animal):
        # 吃
        def eat(self):
            print('猫在吃饭')
           
        # 喝
        def drink(self):
            pass
        def speak(self):
            print('喵喵喵~~')
    # 狗
    class Dog(Animal):
        # 吃
        def eat(self):
            print('狗在吃饭')
        # 喝
        def drink(self):
            pass
        def speak(self):
            print('汪汪汪~~~')
            
    pig = Pig()
    cat = Cat()
    dog = Dog()
    
    pig.speak()
    cat.speak()
    dog.speak()
    

    2.抽象类

    ​ 注意,在Python中不会强制要求子类必须遵循父类的一套标准,所以如果要强制子类遵循父类的一套标准,那么就要使用抽象类。
    ​ 1.是什么?
    ​ 导入 abc(abstract_class)模块
    ​ 2.使用的目的?
    ​ 强制子类必须遵循父类的一套标准
    ​ 3.如何使用?
    ​ import abc

    import abc
    class Animal(metaclass=abc.ABCMeta):
        # 吃
        @abc.abstractmethod
        def eat(self):
            pass
        # 喝
        @abc.abstractmethod
        def drink(self):
            pass
        # 叫
        @abc.abstractmethod
        def speak(self):
            pass
    # Animal() # 父类只是用来建立规范的,不能用来实例化,更无须实现内部的方法。会报错
    # 猪
    class Pig(Animal):  # 子类在继承父类时,就必须遵循父类制定的规范,即遵守父类内部定义的抽象类方法,否则就报错
        # 吃
        def eat(self):
            print('猪在吃饭')
            pass
        # 喝
        def drink(self):
            pass
    
        def speak(self):
            print('哼哼哼~~~')
    
        # 派生
        def run(self):
            pass
    
    pig = Pig()
    

    3.鸭子类型(不推荐强制遵循父类的标准)

    ​ 鸭子类型:在不知道当前对象是何物的情况下,但你长得像鸭子,那你就是鸭子。
    ​ 注意:在Python中,不会强制要求子类必须遵循父类的一套标准,所以出现了鸭子类型。

    # python崇尚鸭子类型
    class Disk:
        def read(self):
            print('Disk read')
    
        def write(self):
            print('Disk write')
    
    class Memory:
        def read(self):
            print('Mem read')
    
        def write(self):
            print('Mem write')
    
    class Cpu:
        def read(self):
            print('Cpu read')
    
        def write(self):
            print('Cpu write')
    
    obj1=Disk()
    obj2=Memory()
    obj3=Cpu()
    
    # 方式1
    obj1.read()
    obj2.read()
    obj3.read()
    
    # 方式2
    def READ(obj):
        obj.read()
    for obj in (obj1,obj2,obj3):
        READ(obj)
    
    

    4.实现多态的三种方式的优缺点

    ​ 继承(继承父类或者抽象类):耦合性太高,扩展性差;
    ​ 鸭子类型:耦合度低,程序的可扩展性强;

    5.容器数据类型与多态之间的联系

    str,list,tuple,dict,set

    # 以列表类型,
    l = [1,2,3,4]  # l是内置类list的一个实例,即对象,通过对象点的方式可以对操作对象类中的方法(内置函数)
    l.append(99)   # 对象(l).方法(append),对象绑定方法
    print(l)  # [1, 2, 3, 4, 99]
    list.append(l,100)  # 类绑定方法,就是普通函数,需将对象作为第一个参数传入
    print(l)  # [1, 2, 3, 4, 99, 100]
    
    print(l.__class__)  # <class 'list'>
    print(l.__class__.__dict__)  # 获取list类名称空间的名字(即list的内置方法)
    print(l.__class__.__name__)  # list
    

    总结:容器数据类型,赋值给一个变量名,这个变量名就是对象,变量名点内置方法就是点对应类里面的方法(技能)。

    示例

    #其实大家一直在享受着多态性带来的好处,比如Python的序列类型有多种形态:字符串,列表,元组,多态性体现如下
    #str,list,tuple都是序列类型
    s=str('hello')
    l=list([1,2,3])
    t=tuple((4,5,6))
    
    #我们可以在不考虑三者类型的前提下使用s,l,t
    s.__len__()
    l.__len__()
    t.__len__()
    
    str1 = '1234'
    list1 = [1, 2, 3]
    def LEN(d):
        return d.__len__()
    
    print(LEN(str1))
    print(LEN(list1))
    
    print(len(str1))
    print(len(list1))
    
  • 相关阅读:
    【LeetCode】1248. 统计「优美子数组」
    【LeetCode】200. 岛屿数量
    【LeetCode】53. 最大子序和
    【剑指Offer】面试题42. 连续子数组的最大和
    【剑指Offer】面试题57. 和为s的两个数字
    【LeetCode】55. 跳跃游戏
    【LeetCode】56. 合并区间
    简历HTML网页版
    关于新建Eclipse新建一个WEB项目后创建一个jsp文件头部报错问题?
    jquery选择器 看这个链接吧!2017.6.2
  • 原文地址:https://www.cnblogs.com/zhangchaocoming/p/11666707.html
Copyright © 2011-2022 走看看