1.接口类

python是没有接口这个概念的

1)引:归一化设计

#第一版:写一个两种支付功能的程序

class Alipay:
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用支付宝支付了%s钱"% self.money)
class JDpay:
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用京东支付了%s钱" % self.money)
a1 = Alipay(100)
a1.pay()
j1 = JDpay(200)
j1.pay()          #同样是支付的功能,但是支付的指令不一样,未统一化设计
输出:
用支付宝支付了100钱
用京东支付了200钱
View Code

问题:同样是支付的功能,但是支付的指令不一样,未统一化设计

#第二版:不同的支付方式,调用同样的支付指令,统一化设计

class Alipay:
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用支付宝支付了%s钱"% self.money)
class JDpay:
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用京东支付了%s钱" % self.money)
def pay(obj):
    obj.pay()
a1 = Alipay(100)
j1 = JDpay(200)
pay(a1)
pay(j1)       #归一化设计
输出:
用支付宝支付了100钱
用京东支付了200钱
View Code

2)接口类/抽象类:

1)定义:制定一个规范,所有继承基类的子类,必须要有基类的抽象方法 ,如果没有基类的抽象方法,子类在实例化对象的时候就会报错

#如果子类继承父类,为重写父类的抽象方法,可强制程序报错

from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self):
        pass
class Alipay(Payment):
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用支付宝支付了%s钱"% self.money)
class JDpay(Payment):
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用京东支付了%s钱" % self.money)
class Wechat(Payment):
    def __init__(self,money):
        self.money = money
    def wechat_pay(self):          #未在子类重写父类抽象方法
        print("用微信支付了%s块" % self.money)
def pay(obj):
    obj.pay()
a1 = Alipay(100)
pay(a1)
j1 = JDpay(200)
pay(j1)
w1 = Wechat(300)
w1.wechat_pay()
报错如下:
TypeError: Can't instantiate abstract class Wechat with abstract methods pay
View Code

#子类重写父类抽象方法

from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
    @abstractmethod
    def pay(self):
        pass
class Alipay(Payment):
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用支付宝支付了%s钱"% self.money)
class JDpay(Payment):
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用京东支付了%s钱" % self.money)
class Wechat(Payment):
    def __init__(self,money):
        self.money = money
    def pay(self):
        print("用微信支付了%s块" % self.money)
def pay(obj):
    obj.pay()
a1 = Alipay(100)
pay(a1)
j1 = JDpay(200)
pay(j1)
w1 = Wechat(300)
w1.pay()
输出:
用支付宝支付了100钱
用京东支付了200钱
用微信支付了300块
View Code

注:必须要在抽象方法前加上@abstractmethod装饰器,否则子类有无重写父类抽象方法都不影响程序,即程序不会报错

2.多态、封装

1)python多态:python是没有多态这个感念的(没有多态的示例),因为python中处处是多态;因为不管是什么数据类型,传入函数,封装到对象中都可以,python是可以多继承的,其他语言不可以

2)python没有多态,但是它又有鸭子类型

#多个类,每一个类中都有同名的方法,且这些方法功能类似;这些类,都互称为鸭子

class Str:
    def index(self):
        pass
class List:
    def index(self):
        pass
class Tuple:
    def index(self):
        pass
View Code

3.封装

1)广义封装:实例化一个对象,给对象空间封装一些属性、给类中封装静态字段

2)狭义的封装:私有制,只有某些对象可以调用

3)私有成员:分为私有静态字段、私有方法、私有对象属性

#python中各变量和方法

class A:

    company_name = '百度'  # 静态变量(静态字段)
    __iphone = '1353333xxxx'  # 私有静态变量(私有静态字段)


    def __init__(self,name,age): #特殊方法

        self.name = name  #对象属性(普通字段)
        self.__age = age  # 私有对象属性(私有普通字段)

    def func1(self):  # 普通方法
        pass

    def __func(self): #私有方法
        print(666)


    @classmethod  # 类方法
    def class_func(cls):
        """ 定义类方法,至少有一个cls参数 """
        print('类方法')

    @staticmethod  #静态方法
    def static_func():
        """ 定义静态方法 ,无默认参数"""
        print('静态方法')

    @property  # 属性
    def prop(self):
        pass
转自:https://www.cnblogs.com/jin-xin/articles/9214247.html
View Code

①私有静态字段:在变量名前加两下划线如【__name】

#实例化对象不能直接访问私有静态字段

class A:
    name = "阿狸"
    __age = 18
    def func(self):
        print("In func...")
a1 = A()
print(a1.name)
print(a1.__age)       #实例化对象不能直接访问私有静态字段
报错:
AttributeError: 'A' object has no attribute '__age'
阿狸
View Code

#类名不能直接访问私有静态变量

class A:
    name = "阿狸"
    __age = 18
    def func(self):
        print("In func...")
a1 = A()
print(A.__age)
输出:
AttributeError: 'A' object has no attribute '__age'
View Code

总结:对于私有静态变量,类的外部不能访问

#对于私有静态字段,类的内部可以访问

class A:
    name = "阿狸"
    __age = 18
    def func(self):
        print("In func...")
        print(A.__age)
a1 = A()
输出:
In func...
18
View Code

#对于私有静态字段,子类不可以访问

总结:对于私有静态字段来说,只能在本类的内部访问,类的外部、派生类都不能访问

备注:实际是可以在类的外部对私有静态字段进行修改的,因为从本质上来说,定义一个类就相当于开辟了一块内存空间,对于私有静态字段如【__name】,实际在内存空间中存的是【_A_name】,所以可在类外直接通过_A__name改变私有静态字段,但是非常不建议这么做

class A:
    name = "阿狸"
    __age = 18
    def func(self):
        print("In func...")
print(A._A__age)
print(A.__dict__)
输出:
18
{'_A__age': 18, 'name': '阿狸', 'func': <function A.func at 0x000001504A05A048>, '__module__': '__main__', '__doc__': None, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>}
View Code

②私有方法:在方法名前加两个下划线【__方法名】

#对于私有方法,在类外不能访问,类的派生类也不能访问,只能在类的内部访问

class A:
    def __func(self):
        print("In func...")
    def func_2(self):
        self.__func()
a1 = A()
a1.func_2()
输出:
In func...
View Code

本质:在开辟内存空间时,把私有方法名改为了【_类名__方法名】

例:写入如下程序的输出

class Parent:
    def __func(self):
        print('in Parent func')

    def __init__(self):
        self.__func()

class Son(Parent):
    def __func(self):
        print('in Son func')

son1 = Son()
输出:
in Parent func
View Code