面向对象的三大特性:继承、封装、多态

Winterto0 2020-01-28

一、python面向对象的三大特性:继承、封装、多态

封装:把很多数据封装到一个对象中。把固定功能的代码封装到一个代码代码块、函数、对象、打包成模块。这都属于封装的思想。具体的情况具体分析,比如,你写了一个很NB的函数,那这个也可以被称之为封装。在面向对象思想中,是把一些看似无关紧要的内容组合到一起统一进行存储和使用,这就是封装。

继承:子类可以自动拥有父类中除了私有属性外的其他所有内容。先有父类再有子类。在python中实现继承非常简单,在声明类的时候,在类名后面添加一个小括号,就可以完成继承关系。

多态:同一个对象,多种形态。

二、封装

封装:将内容封装到某个地方,以后再去调用被封装在某处的内容

# 创建类
class Foo():
    def __init__(self,name,age):
        self.name = name
        self.age = age
        
    def detail(self):
        print(self.name)
        print(self.age)
# 根据类Foo创建对象
# 自动执行Foo类的__init__方法
obj1 = Foo("agen",15)
print(obj1.name)  # 直接调用obj1对象的name属性
print(obj1.age)   # 直接调用obj1对象的age属性
# 通过self间接调用被封装的内容
obj1.detail()   # Python默认会将obj1传给self参数,所以此时方法内部的 self = obj1


# 根据类Foo创建对象
# 自动执行Foo类的__init__方法
obj2 = Foo("alex",15)
print(obj2.name)   # 直接调用obj1对象的name属性
print(obj2.age)   # 直接调用obj1对象的age属性
# 通过self间接调用被封装的内容
obj2.detail()   # Python默认会将obj1传给self参数,所以此时方法内部的 self = obj1

对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取封装的内容。

二、多态

多态:同一个对象,多种形态。python默认支持多态。(创建一个变量a=10,此时a是整数类型,通过程序让a="alex",a又变成了字符串类型,这就是多态性,同一个变量可以是多种形态)

鸭子类型:长得像鸭子,走路像鸭子,叫声也像鸭子,那么你就是鸭子。

三、类的约束

对类的约束有两种:

1、提取父类,然后在父类中定义好方法。在这个方法中什么都不用干,就抛一个异常就可以了,这样所有的子类都必须重写这个方法,否则,访问的时候出错。

2、使用元类来描述父类,在元类中给出一个抽象方方法,这样子类就不得不给出抽象方法的具体实现,也可以起到约束的效果。

第一种方法解决:

class Payment:
    """
    此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
    """
    def pay(self,money):
        raise Exception("你没有实现pay方法")

class QQpay(Payment):
    def pay(self,money):
        print(‘使用qq支付%s元‘ % money)

class Alipay(Payment):
    def pay(self,money):
        print(‘使用阿里支付%s元‘ % money)

class Wechatpay(Payment):
    def fuqian(self,money):
        print(‘使用微信支付%s元‘ % money)


def pay(obj,money):
    obj.pay(money)

a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)

第二种方法:引入抽象类的概念处理。

from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):    # 抽象类 接口类  规范和约束  metaclass指定的是一个元类
    @abstractmethod
    def pay(self):pass  # 抽象方法

class Alipay(Payment):
    def pay(self,money):
        print(‘使用支付宝支付了%s元‘%money)

class QQpay(Payment):
    def pay(self,money):
        print(‘使用qq支付了%s元‘%money)

class Wechatpay(Payment):
    # def pay(self,money):
    #     print(‘使用微信支付了%s元‘%money)
    def recharge(self):pass

def pay(a,money):
    a.pay(money)

a = Alipay()
a.pay(100)
pay(a,100)    # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能
q = QQpay()
q.pay(100)
pay(q,100)
w = Wechatpay()
pay(w,100)   # 到用的时候才会报错



# 抽象类和接口类做的事情 :建立规范
# 制定一个类的metaclass是ABCMeta,
# 那么这个类就变成了一个抽象类(接口类)
# 这个类的主要功能就是建立一个规范

四、super()深入学习

super是严格按照类的继承顺序执行!!!

class A:
    def f1(self):
        print(‘in A f1‘)
    
    def f2(self):
        print(‘in A f2‘)


class Foo(A):
    def f1(self):
        super().f2()
        print(‘in A Foo‘)
        
        
obj = Foo()
obj.f1()
class A:
    def f1(self):
        print(‘in A‘)

class Foo(A):
    def f1(self):
        super().f1()
        print(‘in Foo‘)

class Bar(A):
    def f1(self):
        print(‘in Bar‘)

class Info(Foo,Bar):
    def f1(self):
        super().f1()
        print(‘in Info f1‘)

obj = Info()
obj.f1()

‘‘‘
in Bar
in Foo
in Info f1
‘‘‘
print(Info.mro())  # [<class ‘__main__.Info‘>, <class ‘__main__.Foo‘>, <class ‘__main__.Bar‘>, <class ‘__main__.A‘>, <class ‘object‘>]
class A:
    def f1(self):
        print(‘in A‘)

class Foo(A):
    def f1(self):
        super().f1()
        print(‘in Foo‘)

class Bar(A):
    def f1(self):
        print(‘in Bar‘)

class Info(Foo,Bar):
    def f1(self):
        super(Foo,self).f1()
        print(‘in Info f1‘)

obj = Info()
obj.f1()

相关推荐