继承,组合

Posted waller

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了继承,组合相关的知识,希望对你有一定的参考价值。

继承

什么是继承

继承是一种关系: 描述两个类之间 什么是什么的关系

例: 麦兜,佩奇,猪悟能 都是猪

在程序中,继承描述的是类与类之间的关系

例如:a继承了b,a就能直接舒勇b已经存在的属性方法

a称为子类,b称为父类(基类)

为什么要使用继承:

继承的一方(子类)可以直接使用被继承一方(父类)已经有的东西(属性和方法)

目的: 重用已有的代码,提高重用性

如何使用:

语法:

class 类名称(父类1名称,父类2名称,...)
    代码块
# python中,一个子类可以同时继承多个父类

 

例:

class Sup:
    info = from Sup
    def money(self):
        print(from Sup money)
?
class Sub(Sup):  # Sub 继承 Sup
    pass
obj = Sub()
# 子类调用父类中的属性
print(obj.info)  # >>> from Sup
# 子类调用父类中的方法
obj.money()  # >>> from Sup money

 

抽象:

名词解释:不具体,看不清,很模糊,看不懂

抽象的过程:

1.将多个类中相同的部分(属性或方法),进行抽取,

2.创建一个新的类,把这些相同的部分放到新的类中(这个新类是被抽取的类的大类,)

正确的使用继承:

1.先抽象再继承

2.继承一个已经存在的类,扩展或修改原始功能

图解:技术图片

技术图片

例:老师类和学生类相同的部分有name,age,gender...,老师和学生都属于人,就可以创建一个新类:人类

class Teacher:
    func = teach
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
?
    def say_hi(self):
        print(name:%s, age:%s, gender:%s%(self.name, self.age, self.gender))
?
t = Teacher(haha, 20, male)
print(t.func)
t.say_hi()
?
?
class Student:
    func = play
?
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
?
    def say_hi(self):
        print(name:%s, age:%s, gender:%s % (self.name, self.age, self.gender))
?
s = Student(xixi, 15, male)
print(s.func)
s.say_hi()
?
# 抽象后的到:
?
?
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender
    def say_hi(self):
        print(name:%s, age:%s, gender:%s % (self.name, self.age, self.gender))
?
?
class Teacher(Person):
    func = teach
    def skill_training(self):
        print(教 Python 代码)
        
t = Teacher(haha, 20, male)
print(t.func)  # >>> teach
t.say_hi()  # >>> name:haha, age:20, gender:male
t.skill_training()  # >>> 教 Pythong 代码
?
class Student(Person):
    func = play
?
s = Student(xixi, 15, male)
print(s.func)  # >>> play
s.say_hi()  # >>> name:xixi, age:15, gender:male
?

 

属性的查找顺序

对象自己 ---> 所在类 ---> 父类 ---> Object

class A:
    func = haha
class B(A):
    func = xixi
obj = B()
obj.func = hehe
print(obj.func)  # >>> hehe

 

派生

当一个子类中出现了父类中不同的内容(属性或方法)时,这个子类就称之为派生类

通常子类都会写一些新的代码,不会和父类完全相同,即通常同时派生类

class sup:
    text = 20
    def func(self):
        print(hello)
class sub(sup):
    def auth(self):
        print(hello, world)

 

 

覆盖

也称之为重写 overrides

当子类中出现了与父类中 名称 完全一致的属性会方法

父类中被覆盖的属性会方法子类无法再调用,因为查找顺序:对象-->子类-->父类

class sup:
    text = 20
    def func(self):
        print(hello)
class sub(sup):
    # 覆盖父类中的func函数
    def func(self):
        print(hello, world)

 

练习 : 创建一个可以限制元素类型的列表*

# 把list当做父类,可以使用list中已经写好的代码,不需要再重新写
class MyList(list):
    def __init__(self, my_type):
        # 调用父类的初始化方法,来完成基本的初始化
        super().__init__()  # 因父类的init方法不需要参数,所以不用传参
        self.my_type = my_type
?
    def append(self, obj):
        ‘‘‘
        :param obj:  要添加的元素
        :return: 没有返回值
        ‘‘‘
        if type(obj) == self.my_type:
            # 调用父类(list)里的append方法,来完成真正的存储工作
            super(MyList, self).append(obj)
            # 也可用 super().append(obj)
        else:
            print(添加的元素类型与设定的%s类型不同%self.my_type)
?
# 当你的需求是在创建对象时干点什么事,就该想到__init__初始化方法
m = MyList(int)  # 元素定义为 int 类型
m.append(2)
m.append(4)
m.append(6)
print(m)  # >>> [2, 4, 6]
print(m[1])  # 4
m.append(1)  # 添加的元素类型与设定的<class ‘int‘>类型不同

 

在子类中访问父类的内容

语法:

方式1:
   super(当前类名,self).要调用的父类的属性或方法
方式2:
   super().要调用的父类的属性或方法
   # 方式2 属于python3语法
方式3:
   父类名.要调用的父类的属性或方法(self)
   # 方式3余继承无关

注意(**)

当你继承一个现有的类,并且你覆盖了父类中的双下init方法时,必须在初始化方法的第一行调用父类的初始化方法,并传入父类所需要的参数

class Person:
    def __init__(self,name,gender,age,*args):
        self.name = name
        self.gender = gender
        self.age = age
        self.aa()  # 会执行此函数
?
    def aa(self):
        print("aa run")
?
    def say_hi(self):
        print("name:%s ,gender:%s,age:%s" % (self.name,self.gender,self.age))
?
?
class Student(Person):
    # 覆盖父类的 __init__ 
    def __init__(self,name,gender,age,number):
        # 调用父类的 __init__ 并传参
        super().__init__(name,gender,age)
        self.number= number
?
    def say_hi(self):
        # 调用父类方法
        super().say_hi()
        print("numnber:%s" % self.number)
?
stu = Student("rose","mael",20,"01")
stu.say_hi()
>>>
aa run
name:rose ,gender:mael,age:20
numnber:old01

 


?

组合

组合是一种关系 : 描述两个类之间 什么有什么的关系

例 : 学生有手机,游戏角色有装备...

将一个类的对象作为另一个类的属性传入

什么时候使用继承: 分析两个类之间的关系,到底是不是 什么是什么的关系

什么时候使用组合: 分析两个类之间的关系, 没有太大的关系,完全不属于同类

组合比继承的耦合性更低

 

菱形继承

首先声明 Python 支持多继承 可以通过 子类名.mro() 查看父类的查找顺序,返回的是一个列表

新式类与经典类

python3中的任何类型都是直接或间接的继承Object

新式类: 任何显式或隐式地继承自Object的类就称之为新式类,python3中都是新式类

经典类:既不是Object的子类,仅在python2中出现

菱形继承时

1新式类,先查找深度,当遇到了共同的父类时就查找广度

2.经典类: 按深度查找

以上是关于继承,组合的主要内容,如果未能解决你的问题,请参考以下文章

扫盲-继承与组合

JSJavaScript继承 - 原型链 - 盗用构造函数 - 组合继承 -原型式继承 - 寄生式继承 - 寄生式组合继承

为何说要多用组合少用继承?如何决定该用组合还是继承?

组合与继承

组合继承

对象继承——组合继承