组合、多态和封装

组合

组合的概念

组合指的是,在一个类中以另一个类的对象作为数据属性,称为类的组合,即对象的某个属性是另一个类的对象

class Weapon:
    def knief(self):
        print('这是一把刀')

class Person:
    def __init__(self, name):
        self.name = name
        self.weapon = Weapon()

per = Person('人')
per.weapon.knief()

# 这是一把刀

为什么使用组合

通过组合可以减少代码冗余

没有使用组合,学生和老师的课程的名称/价格/周期都要重新输入

class Person:
    school = 'oldboy'

class Teacher(Person):
    def __init__(self, name, age, course_name, course_price, course_period):
        self.name = name
        self.age = age
        self.course_name = course_name
        self.course_price = course_price
        self.course_period = course_period

class Student(Person):
    def __init__(self, name, age, course_name, course_price, course_period):
        self.name = name
        self.age = age
        self.course_name = course_name
        self.course_price = course_price
        self.course_period = course_period

使用组合,就可以把课程名称/价格/周期单独写在外面

class Person:
    school = 'oldboy'

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

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

class Course:
    def __init__(self, course_name, course_price, course_period):
        self.course_name = course_name
        self.course_price = course_price
        self.course_period = course_period

course = Course('Python', 20100, 7)
stu1 = Student('张三', 19, course)
tea1 = Teacher('李四', 27, course)
print(stu1.course.name)

# Python

小结

组合与继承都是有效地利用已有类的资源的重要方式。但是二者的概念和使用场景皆不同。

  1. 继承的方式

通过继承建立了子类和父类之间的关系,它是一种"是"的关系,比如白马是马。

当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好,比如老师是人,学生也是人。

  1. 组合的方式

用组合的方式建立了类与组合的类之间的关系,它是一种"有"的关系,比如老师有学生1、学生2,老师有课程python、课程Linux

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

多态和多态性

多态

多态指的一类事物有多种形态

比如动物有多种形态:人,狗,猪

class Animal:
    def speak(self):
        pass

class Pig(Animal):
    def speak(self):
        print('哼哼哼')

class Dog(Animal):
    def speak(self):
        print('汪汪汪')

class People(Animal):
    def speak(self):
        print('嘤嘤嘤')

多态性

多态性是指在不考虑实例类型的情况下使用实例

class Animal:
    def speak(self):
        pass

class Pig(Animal):
    def speak(self):
        print('哼哼哼')

class Dog(Animal):
    def speak(self):
        print('汪汪汪')

class People(Animal):
    def speak(self):
        print('嘤嘤嘤')

pig = Pig()
dog = Dog()
people = People()
pig.speak()
dog.speak()
people.speak()

# 哼哼哼
# 汪汪汪
# 嘤嘤嘤

# 也可以定义一个统一的接口来使用
def func(obj):
    obj.speak()

多态性的好处

  1. 增加了程序的灵活性
  2. 增加了程序的可扩展性

约束代码的两种方式

方式一

用abc模块实现接口统一化,约束代码(用的比较少)

import abc
class Animal(metaclass=abc.ABCMeta):   # 在括号中写metaclass=abc.ABCMeta
    @abc.abstractmethod   # 在要约束的方法上,写@abc.abstractmethod装饰器
    def speak(self):
        pass

class Pig(Animal):
    def speak(self):
        print('哼哼哼')

pig = Pig()
pig.speak()

方式二

用异常处理来实现(常用)

class Animal(self):
    def speak(self):
        raise Exception('重写方法')

class Pig(Animal):
	def speak(self):
		print('哼哼哼')

pig = Pig()
pig.speak()

鸭子类型

Python崇尚鸭子类型,即"如果看起来像,叫声像而且走起路来像鸭子,那么它就是鸭子"。Python程序员通常根据这种行为来编写程序的。

封装

封装就好像是拿来一个麻袋,把小猫、小狗,一起装进麻袋,然后把麻袋封上口子。按照这种逻辑,封装="隐藏",这种理解是相当片面的。

封装不是单纯意义的隐藏

隐藏属性/方法:隐藏之后,外部访问不到,只有内部能够访问。

隐藏属性:通过__变量名来隐藏

隐藏方法:通过__方法名来隐藏

隐藏属性:将数据隐藏起来这不是目的。隐藏起来然后对外提供操作该数据的接口,然后我们可以在接口附加上对该数据操作的限制,以此完成对数据属性操作的严格控制,是为了安全。

通过变性隐藏了属性。什么时候属性变性:只要在类内部,以__变量名命名的变量,都会被隐藏,会发生变性,在外部放入的__变量名属性是不隐藏的

隐藏方法:目的是隔离复杂度,提升安全性

封装与扩展性

封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;而外部使用者只知道一个借口,只要这个接口名、参数不变,使用者的代码永远无需改变。这就提供一个良好的合作基础——或者说,只要接口这个基础约定不见,则代码改变不足为虑。

property特性

property装饰器:把方法包装成数据属性

将一个类的方法定义成数据属性后,对象再去使用的时候,无法察觉自己是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则。

posted @ 2019-08-28 20:49  云台三落  阅读(148)  评论(0编辑  收藏  举报