- 接口类和抽象类
- 接口类
- 抽象类
- 两个概念
- python如何实现接口类和抽象类
- 类方法和静态方法
- @classmethod
- 设计目的
- 定义
- 使用类方法的优点
- @staticmethod
- 使用场景
- 区别
具体请参考链接: Python设计模式二:接口类和抽象类(Python接口设计),
我们之所以对这两个概念模糊,是因为Python的原生语法是不支持的,而C++只支持抽象类,java支持接口和抽象类,Go只支持接口类。但在Python里我们可以通过abc这个库来额外实现接口类和抽象类。
关于接口类在其他面向对象语言里称之为interface,
定义:
抽象类接口类相比于普通类:
- 不支持实例化,
- 仅包含抽象方法而不包含属性,
- 实现接口类的必须实现其中所有方法,标识一种has-a的关系,即拥有某种行为的概念。
定义:
两个概念抽象类相比于普通类:
- 不支持实例化,
- 既包含方法也包含属性,子类继承抽象类的属性和方法,
- 其中子类必须覆盖实现抽象类的所有抽象方法。标识一种is-a的关系,即属于某种东西的概念。
| 项目 | Value |
|---|---|
| 基于实现编程 | 子类都继承于父类的实现,如果父类不具备要实现的能力,就重写该方法,随着程序的庞大,后续的维护和扩展会更加困难 |
| 基于接口编程 | 引入接口将父类的部分行为剥离出去 |
Python里通过abc这个库来实现接口类和抽象类,不同于Java这种有明确的语法区分接口类和抽象类,在Python里,这两者只是概念上的区别,在实现上都一致。因为Python没有interface这语言特性,所以接口类本质上也是通过继承来实现的。而接口类的实现类也不同于java的implements关键字,只能通过继承来实现接口特性。
from abc import ABCMeta, abstractclassmethod
class Duck(metaclass=ABCMeta):
mouth = None
ear = None
eye = None
@abstractclassmethod
def eat(self):
pass
# python实现抽象类
class DuckA(Duck):
def eat(self):
print("duckA eat ...")
duck = Duck()
ducka = DuckA()
那接口类如何实现呢?此时我们再定义FlyEnable这一接口类,然后定义FlyWithWings和FlyNoWay继承接口类,然后再让duckA继承需要的实现类来解决,如下:
# python实现接口类
class FlyEnable(metaclass=ABCMeta):
@abstractclassmethod
def fly(self):
pass
class FlyWithWings(FlyEnable):
def fly(self):
print("fly with wings")
class DuckA(Duck, FlyWithWings):
def eat(self):
print("duckA eat ...")
ducka = DuckA()
ducka.eat()
ducka.fly()
类方法和静态方法
对于一个普通的类,需要使用类中的方法的话,就要进行类实例化,但是如果加上了staticmethod和classmethod的话,这个函数可以不通过实例化,直接通过类名进行调用。
@classmethod 设计目的python无法像C++一样,支持多个参数重载的构造函数,用classmethod装饰器定义函数就能够在类对象实例化之前调用这些函数,相当于多个构造函数,解决多个构造函数的代码写在类外面的问题。减少类方法和对象之间联系
定义该方法的第一个参数(cls)指代的就是类本身,classmethod会用这个类来创建并返回最终的实例。
使用类方法的优点使用类方法的另一个好处就是在继承的时候,保证了子类使用可选构造函数构造出来的类是子类的实例而不是父类的实例。
class A(): a = 0 def __init__(self): A.a += 1 @classmethod def get_a(A): return A.a
@staticmethod 使用场景可以通过A.get_a()调用方法
只要要定义的方法里不涉及到self参数,就用静态方法承担。因为这样就表明这个方法和本身的类没有关系,明确的区别出类相关和不相关。
class A():
def __init__(self, name):
self.name = name
@staticmethod
def is_man():
if 'man' == sex:
return True
else:
return False
def hello(self):
if self.is_man():
print('Hello, %s, you are a real man!' % self.name)
区别对于静态方法, 类和对象都能够访问的, 此处可以使用self.is_man,也可以使用A.is_man,
- classmethod是一个函数修饰符,他表示接下来的是一个类方法,对于常见到的叫做实例方法,类方法的第一个参数是cls(类),而实例方法的第一个参数是self,表示该类的一个实例
- 普通对象方法至少需要一个self参数,代表类对象实例
- 类方法有类变量cls传入,从而可以用cls做一些相关的处理,并且有子类继承,调用该方法时,传入的类变量是cls子类,而非父类,对于类方法,可以通过类来调用,如:C.f()–>(类似于C++中的静态方法)
- 静态方法则没有cls变量
参考:
Python中classmethod和staticmethod
python的classmethod和staticmethod
Python中classmethod与staticmethod区别



