You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在派生类中复用基类的映射方法?

问题

假设我有如下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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:23:10