从零开始学设计模式第四天之面向对象编程中抽象类跟接口的区别

95 阅读2分钟
  • 接口跟抽象类的区别
    • 抽象类:
    • 抽象类不允许被实例化,只能被继承。也就是说,你不能new一个抽象类的对象出来
    • 抽象类可以包含属性和方法。方法既可以包含代码的实现,也可以不包含代码的实现。不包含代码实现的方法就叫做抽象方法
    • 子类继承抽象类,必须实现抽象类中的所有抽象方法。
  • 抽象类的举例:
import uuid
from abc import ABCMeta, abstractmethod
from time import time

class Wallet(metaclass=ABCMeta):

    def __init__(self):
        self._id = uuid.uuid4()
        self._create_time = time()
        self._balance = 0
        self._balance_modified_time = time()
        self.test = 'xxx'

    @abstractmethod
    def get_wallet_id(self):  # 装饰器@abstractmethod定义了该方法为抽象方法
        return self._id

    @abstractmethod
    def get_wallet_create_time(self):  # 装饰器@abstractmethod定义了该方法为抽象方法
        return self._create_time

    def get_balance_modified_time(self):
        return self._balance_modified_time

    def increase_balance(self, increase_balance):
        self._balance += increase_balance

    def decrease_balance(self, decrease_balance):
        self._balance -= decrease_balance

class UserWallet(Wallet):
    """子类必须实现基类的抽象方法,否则也会报错"""

    def get_wallet_id(self):  # 装饰器@abstractmethod定义了该方法为抽象方法
        print('输出钱包id', 1)
        return self._id


    def get_wallet_create_time(self):  # 装饰器@abstractmethod定义了该方法为抽象方法
        return self._create_time

if __name__ == '__main__':
    # w = Wallet()  # 这里实例化会报错不能实例化拥有抽象方法的抽象类
    # TypeError: Can't instantiate abstract class Wallet with abstract methods get_wallet_create_time, get_wallet_id
    u = UserWallet()
    u.get_wallet_id()
  • 接口
    • 接口不能包含属性(也就是成员变量)
    • 接口只能声明方法,方法不能包含代码实现
    • 类实现接口的时候,必须实现接口中声明的所有方法
  • python接口的例子:
    • 下面的例子中,接口包含方法不包含实现,因此只要类中定义方法,将实现代码设置出抛异常,强制子类去实现就可以了

# python用普通类来模拟接口
class WalletA(object):
    def get_wallet_id(self):
        raise NotImplementedError("该方法必须实现")
    def get_wallet_create_time(self):
        raise NotImplementedError("该方法必须实现")
  • 在面向对象编程中,什么时候使用抽象类跟接口?
    • 实际上,当我们要表示一种is-a【某某类是】的关系,并且是为了解决代码复用的问题,就使用抽象类,如果要表示应has-a【某某类有】关系的话,并且是为了隐藏实现细节,只注重功能的时候,就可以使用接口。