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

如何用Generic实现Data与Logic类无冗余组合并支持IDE类型提示?

可行方案:泛型协议+动态类生成

你的核心需求是避免手动编写大量Data与Logic的组合子类,同时让IDE能正确识别组合类的属性和方法,且不采用Data作为属性或动态添加属性的方式。可以通过泛型协议(Protocol)+动态生成组合类的方式实现,具体如下:

实现步骤

  1. 保留原有的Data类和Logic类定义
  2. 定义泛型协议,让IDE能识别组合类同时具备Data类的属性和Logic类的方法
  3. 编写工具函数动态生成Data与Logic的组合类,并通过类型转换让IDE识别类型

代码示例

from typing import Protocol, TypeVar, Type, cast, Any

# 定义类型变量,用于泛型约束
T = TypeVar('T')

# 1. 原有的Data类
class Facility:
    facilityName: str
    
class User:
    userName: str

# 2. 定义Logic类的协议,明确方法签名
class GetterLogic(Protocol):
    def getValue(self) -> Any: ...

# 3. 定义泛型组合协议,让IDE知道该类型同时具备T(Data类)的属性和GetterLogic的方法
class DataGetterProtocol(Generic[T], GetterLogic, Protocol):
    pass

# 4. 原有的Logic类实现
class Getter:
    def getValue(self) -> Any:
        # 这里编写你的实际取值逻辑,示例中取第一个非私有属性
        for attr in dir(self):
            if not attr.startswith('_') and attr != 'getValue':
                return getattr(self, attr)
        return None

# 5. 动态生成组合类的工具函数
def get_data_getter(data_cls: Type[T]) -> DataGetterProtocol[T]:
    # 动态创建Data类与Getter类的子类
    combined_cls = type(f"{data_cls.__name__}Getter", (data_cls, Getter), {})
    # 创建实例并通过类型转换让IDE识别类型
    return cast(DataGetterProtocol[T], combined_cls())

# 使用示例
def test():
    return get_data_getter(Facility)

a = test()
a.facilityName  # IDE会自动提示该属性
a.getValue()    # IDE会自动提示该方法

方案优势

  • 无需手动编写每个Data+Logic的组合子类,只需调用工具函数即可生成
  • IDE能通过泛型协议正确识别Data类的属性和Logic类的方法
  • 没有将Data类作为属性存储,也没有动态添加属性,完全基于类继承实现

如果需要支持Setter或其他Logic类,只需按照相同模式扩展:定义对应的Logic协议,然后修改工具函数生成包含多个Logic类的组合子类即可。

内容的提问来源于stack exchange,提问作者Orion

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 05:33:11