类行为问题
问题
类变量在继承过程中,子类直接使用了父类的同一份变量,导致行为错误。
错误代码
class Builder:
_inventory: list
@classmethod
def buildPartA(cls):
raise NotImplementedError
@classmethod
def buildPartB(cls):
raise NotImplementedError
@classmethod
def buildPartC(cls):
raise NotImplementedError
@classmethod
def buildPartD(cls):
raise NotImplementedError
@classmethod
def get_result(cls):
print(cls._inventory)
@classmethod
def add_to_inventory(cls, good):
print(dir(cls))
cls._inventory.append(good)
class BMWBuilder(Builder):
@classmethod
def buildPartA(cls):
print("Build BMW PartA")
cls.add_to_inventory("PartA")
@classmethod
def buildPartB(cls):
print("Build BMW PartB")
cls.add_to_inventory("PartB")
@classmethod
def buildPartC(cls):
print("Build BMW PartC")
cls.add_to_inventory("PartC")
@classmethod
def buildPartD(cls):
print("Build BMW PartD")
cls.add_to_inventory("PartD")
class BenzBuilder(Builder):
@classmethod
def buildPartA(cls):
print("Build Benz PartA")
cls.add_to_inventory("PartA")
@classmethod
def buildPartB(cls):
print("Build Benz PartB")
cls.add_to_inventory("PartB")
@classmethod
def buildPartC(cls):
print("Build Benz PartC")
cls.add_to_inventory("PartC")
@classmethod
def buildPartD(cls):
print("Build Benz PartD")
cls.add_to_inventory("PartD")
class Manager:
def __init__(self, builder: Builder = None):
self.builder = builder
def set_builder(self, builder: Builder):
self.builder = builder
def build(self):
self.builder.buildPartA()
self.builder.buildPartB()
self.builder.buildPartC()
self.builder.buildPartD()
self.builder.get_result()
if __name__ == "__main__":
def test():
manager = Manager()
builder = BMWBuilder()
manager.set_builder(builder)
manager.build()
builder = BenzBuilder()
manager.set_builder(builder)
manager.build()
test()
解决方案
用metaclass去控制类的行为
class BuilderMeta(type):
def __new__(mcs, cls_name, cls_bases, cls_dict):
cls_dict["_inventory"] = []
return type.__new__(mcs, cls_name, cls_bases, cls_dict)
class Builder(metaclass=BuilderMeta):
...