• python-33 面向对象之二:组合、继承


     

    1.当类之间有显著的不同,并且较小的类是较大的类所需要的组件时,用组合较好

    '''
    1.组合:在一个类中以另外一个类的对象作为数据属性,称为类的组合
    '''
    class School:
        def __init__(self,name,add):
            self.name=name
            self.add=add
    
    class Course:
        def __init__(self,name,price,priod,school):
            self.name=name
            self.price=price
            self.priod=priod
            self.school=school  #传入一个类,这样就构成了一个组合,一类中包含了另一个类
    
    s1=School('清华','北京')
    s2=School('科大','合肥')
    
    c1=Course('python','1w','3mon',s1) #这就是组合,大类中包含小类
    c2=Course('linux','2w','4mon',s2)
    
    print(c1.school.name)
    print(s1,'
    ',c1.__dict__['school'])#打印 s1内存地址,地址相同
    View Code

     2.当类之间有许多共同的功能,提取这些共同的功能做基类,用继承较好

        继承:具有两方面含义,一是继承父类的特性,二是具有自己衍生的特性

       单继承:从上往下继承,先继承祖先类,再继承子孙类的类数据属性和方法属性,实例化时,先查找自己的__init__方法,没有再往上找,直到找到为止,

                       如果都没有显示的__init__方法,调用object类的__init__方法

    class A:
        print('---A---')
        def __init__(self,name):
            self.name=name
            print('A:name=%s'%self.name)
        def eat(self):
            print('%s正在吃ing'%self.name)
    class B(A):
        a=1
        print('---B---')
    class C(B):
        print('---C---')
        def __init__(self,sex,age):
            self.g=super().__init__('小a')
            self.sex=sex
            self.age=age
            print('C:sex=%s  age=%s'%(sex,age))
    
    c=C('boy',50)#先打印 B C类的数据属性,相当于先将打印的代码加载到C类中,再调用父类的__init__,最后是自身的__init__方法
    c.eat()#小a正在吃ing
    print(c.__dict__)#{'name': '小a', 'g': None, 'sex': 'boy', 'age': 50},拥有了name数据属性
    View Code

     

    多继承:根据mro线性顺序表继承(广度优先查找),同样先继承所有父类的数据属性,再查找__init__,调用了哪个父类的__init__方法,就继承了该父类的所有其它方法属性,未被调用的父类,则不继承该父类的方法属性。

    '''
    1.组合:在一个类中以另外一个类的对象作为数据属性,称为类的组合
    '''
    class School:
        def __init__(self,name,add):
            self.name=name
            self.add=add
    
    class Course:
        def __init__(self,name,price,priod,school):
            self.name=name
            self.price=price
            self.priod=priod
            self.school=school  #传入一个类,这样就构成了一个组合,一类中包含了另一个类
    
    s1=School('清华','北京')
    s2=School('科大','合肥')
    
    c1=Course('python','1w','3mon',s1) #这就是组合,大类中包含小类
    c2=Course('linux','2w','4mon',s2)
    
    print(c1.school.name)
    print(s1,'
    ',c1.__dict__['school'])#打印 s1内存地址,地址相同
    
    '''
     2. 继承:新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
         python中类的继承分为:单继承和多继承
    '''
    class Father:
        money=100   #继承类的属性和方法
        def __init__(self,name):
            self.name=name
            print('这是爸爸【name=%s】类'%self.name)
        def Habit(self):
            print('爸爸【name=%s】的坏习性:爱抽烟'%self.name)
        def work(self):
            print('Father教学生')
    class Mother:
        car='路虎'
        def __init__(self,age,national ):
            self.age=age
            self.national=national
            print('这是妈妈【age=%d】类'%self.age)
        def Hobby(self):
            print('妈妈【age=%d】的爱好是打球'%self.age)
    
    class Son(Father,Mother): #可以多继承,但实例化时,若自身没有__init__,则调用第一个父类的__init__,即Father.__init__
        def work(self):
           print('Son开汽车')
    
    
    print(Father.__dict__)
    print(Mother.__dict__)
    print(Son.__dict__) #不包含父母类的任何属性{'__module__': '__main__', 'work': <function Son.work at 0x000000000225A0D0>, '__doc__': None}
    
    f=Father('大明')#创建Father对象,调用__init__实例化一个f对象,返回:这是爸爸【name=大明】类
    m=Mother(30,'美国人')# 这是妈妈【age=30】类
    
    print(Son.__base__)#__base__只查看从左到右继承的第一个父类,<class '__main__.Father'>
    print(Son.__bases__)#__bases__,查看所有父类,(<class '__main__.Father'>, <class '__main__.Mother'>)
    
    s=Son('小明')#先调用自己的__init__,没有则调用继承的第一个父类,Father.__init__实例化一个s对象,故返回:这是爸爸【name=小明】类,
    
    print(s.name,s.car,s.money)#能调用父母类的静态数据属性,小明 路虎 100
    s.Habit()#能调用父类的方法属性,爸爸【name=小明】的坏习性:爱抽烟
    s.work()#Son开汽车---->方法名相同,并不会改写父类的方法,
    f.work()#Father教学生---->父类方法不变
    
    s.Hobby()#出错,AttributeError: 'Son' object has no attribute 'age',因为实例化时调用的是第一个父类Father.__init_
    View Code
    class Grandpa:
        language='英语'
        def tell(self):
            print('Grandpa会讲%s'%self.language)
    
    class Son1(Grandpa,Mother):
        def job(self):
            print('Son1 is a driver')
    s1=Son1(15,'中国')
    s1.Hobby()#这是妈妈【age=15】类,妈妈【age=15】的爱好是打球,Grandpa类没有.__init__,就调用Mother.__init__
    print(Son1.mro())#继承顺序:[<class '__main__.Son1'>, <class '__main__.Grandpa'>, <class '__main__.Mother'>, <class 'object'>]
    View Code

     总结:类中的方法属性都是与具体对象绑定的,而数据属性无具体对象绑定,所以,在多继承中,只有实例化了父类,即调用了父类的__init__方法后,才能调用该父类的其它方法属性,而没  有被实例化的父类,则不会继承其方法属性,但具有其数据属性。至于@staticmethod的类工具包,既不绑定类又不绑定对象的方法属性,是能继承的。@classmethod,类方法,也是被类继承。

  • 相关阅读:
    hibernate中的所有属性
    新闻系统(3)内容保护的探索
    Hibernate常见问题集锦
    java对象序列化java.io.Serializable 接口实践
    读写属性文件
    Struts 中的自定义异常
    JAVA程序员看C#的精华与糟粕
    正确理解hibernate的inverse属性
    HTML5中的WebSocket
    【转载】 单元测试:是否针对非 public method 进行测试?
  • 原文地址:https://www.cnblogs.com/Zhouzg-2018/p/10279934.html
Copyright © 2020-2023  润新知