##################################################
目录
全网最通俗易懂的 Python 接口与多态以及抽象类抽象方法
使用抽象类和抽象方法定义接口!这是 Python 中真正的接口
##################################################
活动简介
活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰;一个人摸索学习很难坚持,想组团高效学习;想写博客但无从下手,急需写作干货注入能量;热爱写作,愿意让自己成为更好的人…
…
欢迎参与CSDN学习挑战赛,成为更好的自己,请参考活动中各位优质专栏博主的免费高质量专栏资源(这部分优质资源是活动限时免费开放喔~),按照自身的学习领域和学习进度学习并记录自己的学习过程,或者按照自己的理解发布专栏学习作品!
##################################################
全网最通俗易懂的 Python 接口与多态以及抽象类抽象方法
——————————
Python 接口与抽象类抽象方法
%%%%%
Java 接口与 Python 接口
接口/Interface 在 Java 语言中是一个抽象类型 是抽象方法的集合:
Java 接口通常以 interface 来声明
一个类通过继承接口的方式来继承接口的抽象方法
接口并不是类
编写接口的方式和类很相似 但是她们属于不同的概念
类描述对象的属性和方法
接口则包含类要实现的方法
除非实现接口的类是抽象类 否则该类要定义接口中的所有方法!
接口无法被实例化 但是可以被实现
一个实现接口的类 必须实现接口内所描述的所有方法 否则就必须声明为抽象类
在 Java 中接口类型可用来声明一个变量
可以成为一个空指针
或是被绑定在一个以此接口实现的对象
在 Python 中接口由抽象类和抽象方法去实现
接口是不能被实例化的!只能被别的类继承去实现相应的功能
接口在 Python 中并没有那么重要
因为如果要继承接口 需要把其中的每个方法全部实现 否则会报编译错误……
还不如直接定义一个 class 其中的方法实现全部为 pass 让子类重写这些函数……
当然如果有强制要求必须所有的实现类都必须按照接口中的定义写的话 就必须要用接口!
%%%%%
用普通类定义可以被实例化的假接口..
VSCode demo:
class InterFace():
# 假设这就是一个接口 接口名可以随意定义 所有的子类不需要实现在这个类中的函数
def a(self):
# 函数 a
print ( "我是虚拟接口 InterFace 的 a 函数.." )
def b(self):
# 函数 b
pass
class IF_1(InterFace):
# 第一个继承上面定义的接口父类的类
def __init__ (self):
# 该类魔术方法
pass
def a ( self ):
print ( "继承 InterFace 接口 实现 a 函数.." )
class IF_2(InterFace):
# 第二个继承上面定义的接口父类的类
def __init__ (self):
# 该类魔术方法
pass
def b ( self ):
print ( "继承 InterFace 接口 实现 b 函数.." )
if_1 = InterFace() # 因为是假设所以这个 “接口” 可以实例化我靠……
if_1.a()
if_2 = IF_1() # 实例化继承接口类 执行其中的方法
if_2.a()
if_3 = IF_2()
if_3.b()
VSCode demo:
Windows PowerShell
版权所有 (C) 2014 Microsoft Corporation。保留所有权利。
PS C:\Users\byme> python -u "e:\PY\test.py"
我是虚拟接口 InterFace 的 a 函数..
继承 InterFace 接口 实现 a 函数..
继承 InterFace 接口 实现 b 函数..
PS C:\Users\byme>
%%%%%
使用抽象类和抽象方法定义接口!这是 Python 中真正的接口
其实所谓接口是一种特殊的类
这个特殊类中声明了若干方法要求继承该接口的类必须实现这些方法否则会报错!
作用:
限制继承接口的类的方法的名称及调用方式 隐藏了类的内部实现
接口就是一种抽象的 基类/父类 限制继承她的类必须实现接口中定义的某些方法
抽象类加抽象方法就等于面向对象编程中的接口
VSCode code:
from abc import ABCMeta,abstractmethod
# Python 本身不提供抽象类和接口机制 要想实现抽象类 可以借助 abc 模块
# ABCMeta 是抽象类用的
# abstractmethod 抽象方法用的
# 这是定义的钱钱接口
class Money(metaclass=ABCMeta): # 在后面括号中定义这是一个抽象类
# 或者不在括号中指定 像下面这行注释一样指定这是一个抽象类:
# __metaclass__ = ABCMeta
@abstractmethod # 表明这是一个抽象方法
def pay(self, money):
# 这是支付抽象方法
pass
class QQ_Money ( Money ):
# QQ 支付类 继承于 Money 抽象父类
# 注意 这是真正的接口 必须实现继承的父类接口里的所有函数 否则编译错误!
def __init__ ( self ):
# 这是本类魔法函数
print ( "这是接口的实现 1" )
def pay ( self, money ):
# 实现的父类函数
print ( "扣扣钱包支付 [$ %s]" % money )
class WeChat_Money(Money):
# VX 支付类 继承于 Money 抽象父类
def __init__ ( self ):
# 本类被调用自动执行
print ( "这是接口的实现 2" )
def pay(self, money):
# 实现的 Money 父类的 pay 方法
print("微信支付 [%s] 元" % money)
qm_1 = QQ_Money() # 扣扣钱包支付
qm_1.pay ( 521 )
print () # 换行
wm_1 = WeChat_Money() # 微信钱包支付
wm_1.pay(1314)
VSCode demo:
Windows PowerShell
版权所有 (C) 2014 Microsoft Corporation。保留所有权利。
PS C:\Users\byme> python -u "e:\PY\test.py"
这是接口的实现 1
扣扣钱包支付 [$ 521]
这是接口的实现 2
微信支付 [1314] 元
PS C:\Users\byme>
——————————
Python 多态
对于面向对象编程来说 有三个概念一定要知道:
封装
继承
多态
Python 本身就是一种多态语言 —— 即不同的类中可以定义相同的函数名 !!!
%%%%%
何谓多态
继承机制的出现
导致父类和子类相同行为出现的可能
以及在实际运行中的动态结果
此为多态!
多态从定义角度出发来看是:
同一类事物的多种形态
如狗的多种形态 白狗、黑狗、花狗 等
多态性是从使用角度出发的话:
同一种调用方式出现不同的执行效果
具有不同功能的函数可以使用相同的函数名
这样就可以用一个函数名调用不同内容的函数!
多态性依赖于继承机制并且要定义统一的接口!
在 Python 中多态实质就是定义了一个函数接口
在这个函数中定义了所有类中通用的功能
根据不同对象的相同调用接口 就得到不同的结果
%%%%%
经典示例多态 —— 吃出不同的食物
下面这个例子
吃类中有一个空的 eat 方法
食物类全部继承吃类
继承后必须在类中重写父类的方法
所以都是继承吃类但是结果却是吃的不同的东西!!!
VSCode code:
class Eat:
# 吃类 这是父类!!!
def eat(self):
# 继承的子类必须实现该函数
pass # pass 表示该方法为空
class Noodle ( Eat ) :
# 面条类 继承吃类
def eat ( self ):
# 多态必须实现父类的方法
print ( "正在吸面条~" )
class Rice(Eat):
# 米饭类
def eat(self):
# 实现父类方法
print("正在干大米!")
class Flapjack ( Eat ):
# 烙饼类
def eat ( self ):
# 实现父类函数
print ( "正在啃烙饼.." )
noodle_1 = Noodle() # 实例化一个面条对象
noodle_1.eat() # 吃面条
rice_1 = Rice() # 实例化米饭对象
rice_1.eat() # 吃米饭
flapjack_1 = Flapjack() # 实例化烙饼对象
flapjack_1.eat() # 吃烙饼
VSCode demo:
Windows PowerShell
版权所有 (C) 2014 Microsoft Corporation。保留所有权利。
PS C:\Users\byme> python -u "e:\PY\test.py"
正在吸面条~
正在干大米!
正在啃烙饼..
PS C:\Users\byme>
##################################################
通过实例对象级别说明 Python 的类属性访问
——————————
根据属性解析类实例级别和对象实例级别对象
Python 语言中 属性 分为类级别和实例级别两种
实例级别的属性值默认共享类级别的属性值
除非显式进行赋值操作!
看这段交互执行:
Microsoft Windows [版本 6.3.9600]
(c) 2013 Microsoft Corporation。保留所有权利。
C:\Users\byme>python
Python 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> class A:
... i = 521
...
>>> a_1 = A()
>>> a_2 = A()
>>> A.i
521
>>> a_1.i
521
>>> a_2.i
521
>>>
上面这段例子 存在三个实例对象 分别是
class A:
# 类实例对象
i = 521
a_1 = A() # 普通实例对象
a_2 = A() # 普通实例对象
类实例对象 A
实例对象 a_1
实例对象 a_2
a_1 和 a_2 这两个对象实例共享类实例对象 A 的 i 属性!
>>> a_1 = A()
>>> a_2 = A()
>>> A.i
521
>>> a_1.i
521
>>> a_2.i
521
>>>
修改访问类实例对象或普通实例对象的属性值:
>>> print ( A.i, a_1.i, a_2.i )
521 521 521
>>> print ( (A.i - 1), a_1.i, a_2.i )
520 521 521
>>> print ( A.i, (a_1.i - 1), a_2.i )
521 520 521
>>>
现在我们已经修改了对象实例 a_1 的属性值 i
其属性值和类实例A的属性值已经独立
而对象实例 a_2 的属性从来没有修改过 所以她还是和类实例 A 的属性值保持一致
%%%%%
再次强调类属性的访问
Python 语言对于属性的访问采用如下两种方法:
类.属性 = 值
实例.属性 = 值
Python 语言中的属性操作遵循三个规则:
属性的获取是按照从下到上的顺序来查找属性
类和实例是两个完全独立的对象
属性设置是针对实例本身进行的