如何在派生类中复用基类的映射方法?
问题
假设我有如下Python代码(实际语言不限,PHP等其他语言也存在该问题):定义基类CarModel和继承自它的派生类TruckModel。
class CarModel: def __init__(self): self.__wheel_count: int = 0 def set_wheel_count(self, value: int) -> None: self.__wheel_count = value class TruckModel(CarModel): def __init__(self): super().__init__() self.__load_in_kg: int = 0 def set_load_in_kg(self, value: int) -> None: self.__load_in_kg= value
现在我有一个用于将Dict转换为模型的VehicleMapper类,如何在派生类的映射方法中复用基类的映射方法?尤其是当基类有大量setter方法时,重复代码违反DRY原则。
class VehicleMapper: def map_car_dict_to_car_model(dict: Dict) -> CarModel: model: CarModel = CarModel() model.set_wheel_count(dict['wheelCount']) return model def map_truck_dict_to_truck_model(dict: Dict) -> TruckModel: model: TruckModel= TruckModel() model.set_load_in_kg(dict['loadInKg']) model.set_wheel_count(dict['wheelCount']) # ???如何复用基类的映射方法??? return model
我可以将映射方法移到模型类中,但我学到模型类应仅存储数据,不应包含业务逻辑,这正是映射类存在的原因,该如何解决?
解决方案
方法一:抽离基类映射的通用私有方法
把基类的字段映射逻辑单独抽成私有方法,子类映射时直接调用这个方法,既避免重复代码,又保持所有映射逻辑集中在VehicleMapper类中。
from typing import Dict class VehicleMapper: @staticmethod def __map_car_base_fields(model: CarModel, data: Dict) -> None: # 集中处理基类所有字段的映射,后续基类字段修改只需要改这里 model.set_wheel_count(data['wheelCount']) @staticmethod def map_car_dict_to_car_model(data: Dict) -> CarModel: model = CarModel() VehicleMapper.__map_car_base_fields(model, data) return model @staticmethod def map_truck_dict_to_truck_model(data: Dict) -> TruckModel: model = TruckModel() # 先复用基类字段映射逻辑 VehicleMapper.__map_car_base_fields(model, data) # 再处理子类独有的字段 model.set_load_in_kg(data['loadInKg']) return model
这种方式的优势:
- 基类映射逻辑只实现一次,所有子类共享
- 符合单一职责原则,映射逻辑全在
VehicleMapper中 - 基类字段变更时,只需修改一处代码
方法二:让基类映射方法支持传入已有实例
修改基类映射方法,允许传入已创建的模型实例,而不是每次都新建。这样子类可以先创建自己的实例,再传给基类方法完成基类字段的映射。
from typing import Dict, TypeVar T = TypeVar('T', bound=CarModel) class VehicleMapper: @staticmethod def map_car_dict_to_model(data: Dict, model: T) -> T: model.set_wheel_count(data['wheelCount']) return model @staticmethod def map_car_dict_to_car_model(data: Dict) -> CarModel: return VehicleMapper.map_car_dict_to_model(data, CarModel()) @staticmethod def map_truck_dict_to_truck_model(data: Dict) -> TruckModel: truck_model = TruckModel() # 复用基类映射逻辑,传入已创建的truck实例 VehicleMapper.map_car_dict_to_model(data, truck_model) truck_model.set_load_in_kg(data['loadInKg']) return truck_model
这种方式的好处:
- 基类映射方法灵活性更高,既可以创建新实例,也能更新已有实例
- 子类映射逻辑清晰,步骤明确
方法三:映射类继承(适合多子类场景)
如果后续有更多子类需要映射,可以让映射类也遵循继承关系,用基类映射类处理通用逻辑,子类映射类扩展自身逻辑,避免单个映射类过于臃肿。
from typing import Dict class BaseVehicleMapper: @staticmethod def _map_base_fields(model: CarModel, data: Dict) -> None: model.set_wheel_count(data['wheelCount']) class CarMapper(BaseVehicleMapper): @staticmethod def map_to_model(data: Dict) -> CarModel: model = CarModel() BaseVehicleMapper._map_base_fields(model, data) return model class TruckMapper(BaseVehicleMapper): @staticmethod def map_to_model(data: Dict) -> TruckModel: model = TruckModel() BaseVehicleMapper._map_base_fields(model, data) model.set_load_in_kg(data['loadInKg']) return model # 使用示例 car = CarMapper.map_to_model({'wheelCount':4}) truck = TruckMapper.map_to_model({'wheelCount':6, 'loadInKg':5000})
这种方式适合模型类型较多的项目,能更好地组织映射逻辑。
内容的提问来源于stack exchange,提问作者briston82
相关产品推荐
相关产品推荐

