面对对象之三大特点(多态(组合),封装)

一,组合

1,什么是组合

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

class Foo:

    pass

class Bar:
    pass

obj=Foo()
obj.attr=Bar()

obj.xxx
obj.attr.yyy

2,为何要用组合

通过为某一个对象添加属性(属性的值是另外一个类的对象)的方式,可以间接地将两个类关联/整合/组合到一起

从而减少类与类之间代码冗余

扫描二维码关注公众号,回复: 2924077 查看本文章

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,如何用组合

class OldboyPeople:

    school='Oldboy'

    def __init__(self,name,age,sex):

        self.name = name

        self.age = age

        self.sex = sex

class OldboyStudent(OldboyPeople):

    def __init__(self,name,age,sex,score):

         OldboypPeople.__init__(self,name,age,sex)

         self.score = score

    def choose_course(self):
        print('%s choosing course' % self.name)

class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        OldboyPeople.__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=OldboyStudent('刘二蛋',38,'male')
stu1.course=python

stu1.course.tell_info()  # 输出格式

#   创建一个教室对象

tea1=OldboyTeacher('egon',18,'male',10)
tea1.course=python
# print(tea1.__dict__)
tea1.course.tell_info()

二,多态与多态性

1,什么是多态

    多态指的是同一种/类事物的不同形态

2,为何要用多态

多态性:在多态的背景下,可以在不用考虑对象具体类型的前提下而直接使用对象

多态性的精髓:统一

3,如何要用多态

import abc

class Animal(metaclass=abc.ABCMeta):   # 强制要求子类严格按父类的格式来
    @abc.abstractmethod
    def speak(self):
        pass

    @abc.abstractmethod
    def run(self):
        pass

# Animal() # 父类只是用来建立规范的,不能用来实例化的,更无需实现内部的方法

class People(Animal):
    def speak(self):
        print('say hello')

    def run(self):
        pass

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

    def run(self):
        pass

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

    def run(self):
        pass

obj1=People()
obj2=Dog()
obj3=Pig()

鸭子类型:长得像鸭子就认为是鸭子   #没有父类好多子类(没有直接的关系)的实现的方法都一样,从多态的角度就

可以认为这些子类就是鸭子

规定:有text()方法的类都是鸭子

下面很多子类产生的对象都可以调用text()方法

####### 这里缺一个老师补课时举得例子,帮助理解
三,封装(出发点就是安全)

1,什么是封装

装:往容器/名称空间里存放名字

封:代表将存放于名称空间中的名字给藏起来,这种隐藏对外不对内

2,为何要封装

分两种,封数据属性

            封函数属性

3,如何封装

在类内定义的属性前加__开头(没有__结尾)

总结:

1,__开头的属性实现的隐藏仅仅只是一种语法意义上的变形,并不会真的限制类外部的访问

2,该变形操作只在类的定义阶段检测语法时发生一次,类定义阶段之后新增的__开头的属性并不会变形

#   在增加属性是__开头的属性并不会变形

3,如果父类不想让子类覆盖自己的属性,可以在属性的前面加__开头

class Foo:
    __x=111      # _Foo__x
    __y=222       # _Foo__y

    def __init__(self,name,age):
        self.__name=name
        self.__age=age

    def __func(self): #_Foo__func
        print('func')

    def get_info(self):
        print(self.__name,self.__age,self.__x)     #print(self._Foo__name,self._Foo__age,self._Foo__x)

obj = Foo()

obj.__x   #会报错,根本找不到__x

# 封装数据属性:将数据属性隐藏起来,类外就无法直接操作属性,需要类内开辟一个接口来外部可以间接地操作属性,可以在接口内定义任意的控制逻辑,从而严格控制使用对属性的操作

#  封装函数的属性:隔离复杂度

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

    def tell_info(self):
        print('<name:%s age:%s>'  %(self.__name,self.__age))

    def set_info(self,name,age):
        if type(name) is not str:
            print('名字必须是str类型傻叉')
            return
        if type(age) is not int:
            print('年龄必须是int类型傻叉')
            return
        self.__name=name
        self.__age=age


obj=People('egon',18)
# obj.tell_info()

# obj.set_info('EGON',19)
# obj.set_info(123,19)
obj.set_info('EGON','18')
obj.tell_info()

猜你喜欢

转载自blog.csdn.net/qq_42737056/article/details/81907059
今日推荐