首页 » 编程 » Python » 正文

继承、派生,组合,接口归一化设计,抽象类

day28

继承

参阅博客:http://www.cnblogs.com/linhaifeng/articles/7340153.html


什么是继承,从语法角度:

class A:  # 父类A
    pass

class B:  # 父类B
    pass

class C(A):  # 子类C,继承父类A
    pass

class D(A, B):  # 子类D,继承父类A和B,python可以同时继承多个父类
    pass

继承是一种创建新的类的方式。

继承是一种“是”的关系:

人类、猪类、狗类都是继承动物类,因因而他们都是动物。


如何寻找继承关系:


为什么要用继承:

解决代码重用问题。

解决的是:什么是什么的问题


派生

子类继承了父类的属性,然后衍生出自己的属性,如果子类衍生出的新的属性与父类的某个属性名字相同,那么再调用子类的这个属性,就以子类自己这里的为准了。

在子类中重用父类的函数:父类名.父类的函数(函数)

class People:
    def __init__(self, name, sex, age):
        self.name = name
        self.sex = self
        self.age = age

    def walk(self):
        print("%s is walking.." % (self.name))


class Chinese(People):
    country = "China"

    def __init__(self, name, sex, age, language="Chinese"):  # 派生出一个子类自己的方法,比父类多了language参数
        # self.name=name
        # self.sex=sex
        # self.age=age
        People.__init__(self, name, sex, age)  # 重用父类的方法,上面三行代码即可省略
        self.langueage = language


class North_korean(People):
    country = "Korea"


c = Chinese("alex", "male", 18)
print(c.name, c.country, c.langueage)
c.walk()

运行结果:

alex China Chinese
alex is walking..

组合

参阅博客:http://www.cnblogs.com/linhaifeng/articles/7340153.html#_label5

组合对比继承来说,也是用来重用代码,但是组合描述的是一种“有”的关系。

如:

老师有课程

学生有成绩

学校有老师

学校有学生

class Teacher:
    def __init__(self, name, sex, course):
        self.name = name
        self.sex = sex
        self.course = course


class Student:
    def __init__(self, name, sex, course):
        self.name = name
        self.sex = sex
        self.course = course


class Course:
    def __init__(self, name, price, period):
        self.name = name
        self.price = price
        self.period = period


python_obj = Course("python", "15800", "7m")
t1 = Teacher("egon", "male", python_obj)
s1 = Student("alex", "male", python_obj)

print(t1.course.name)
print(s1.course.name)

运行结果:

python
python


接口与归一化设计

参阅博客:http://www.cnblogs.com/linhaifeng/articles/7340153.html#_label6

Java有interface来定义接口,但是Python没有接口这么一说,但是可以通过继承来模拟。

归一化设计:如人和猪都能吃能跑,对于调用者而言,我只需要调用吃或跑的方法就行,至于人和猪各自是怎么跑的便不用管。

# 接口与归一化设计
class Animal:
    def eat(self):
        pass

    def run(self):
        pass


class Poeple(Animal):
    def eat(self):
        print("人在吃")

    def run(self):
        print("人在跑")


class Pig(Animal):
    def eat(self):
        print("猪在吃")

    def run(self):
        print("猪在跑")


poe = Poeple()
poe.eat()

pig = Pig()
pig.eat()

运行结果:

人在吃

猪在吃


上面的例子如果子类没有对接口(父类)方法进行实现也不会报错,没有实现便会到父类去找,但是接口应该是只起定义作用,最好是子类各自进行实现,如何限制子类必须进行实现呢,如下:

# 接口与归一化设计
class Animal:
    def eat(self):
        raise AttributeError("子类必须要实现这个方法")

    def run(self):
        raise AttributeError("子类必须要实现这个方法")  # 当子类没有进行方法实现的时候抛出异常信息


class Poeple(Animal):
    def eat(self):
        print("人在吃")

        # def run(self):
        #     print("人在跑")


poe = Poeple()
poe.run()  # 子类未对run()方法进行实现,会报错

运行结果:

Traceback (most recent call last):
  File "D:/PycharmProjects/python_fullstack_s4/day28/接口与归一化设计.py", line 19, in <module>
    poe.run()   # 子类未对run()方法进行实现,会报错
  File "D:/PycharmProjects/python_fullstack_s4/day28/接口与归一化设计.py", line 7, in run
    raise AttributeError("子类必须要实现这个方法")
AttributeError: 子类必须要实现这个方法


用raise的方式比较low,还可以引入抽象类的方式进行修改,如下:

导入abc模块进行实现:

import abc


class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def eat(self):
        pass

    @abc.abstractmethod
    def run(self):
        pass


class Poeple(Animal):
    def eat(self):
        print("人在吃")

        # def run(self):
        #     print("人在跑")


poe = Poeple()
poe.run()  # 子类未对run()方法进行实现,会报错

运行结果:

Traceback (most recent call last):
  File "D:/PycharmProjects/python_fullstack_s4/day28/抽象类.py", line 22, in <module>
    poe = Poeple()
TypeError: Can't instantiate abstract class Poeple with abstract methods run

抽象类

如上例子。

另参阅博客:http://www.cnblogs.com/linhaifeng/articles/7340153.html#_label7




发表评论

*