pecs原则在低代码动态脚本组件中要求输入端口用? super t(consumer)、输出端口用? extends t(producer):输入接纳子类型并安全添加,输出保证子类型可安全向上转型,避免classcastexception与编译拒绝。

PECS 原则在低代码平台动态脚本组件中的应用,核心不是套用语法,而是明确每个数据端口的“角色”:是往外吐数据(Producer),还是往里收数据(Consumer)。动态脚本组件常对接表单、列表、API响应等多源输入,又需将结果安全透出给后续节点。若不划清读写边界,极易出现类型擦除后运行时 ClassCastException,或编译期拒绝合法调用。
输入端口:一律用 ? super T,接纳上游任意子类型
脚本组件的输入字段(如 inputList、filterCondition、configMap)本质是“消费者”。它要能接收来自不同来源的数据——可能是 List
- 声明为 List super Person>,允许传入 List
、List 、List ,add(new Student()) 安全通过 - 避免声明为 List
:会拒绝 List ,强制用户做无意义转型或中间包装 - 读取时仅按 Object 处理(如 item.toString()),或配合 instanceof + 强转做有限校验,不依赖泛型推导
输出端口:一律用 ? extends T,保证下游可安全向上转型
脚本执行后返回的结果(如 outputData、transformedItems、summaryStats)是“生产者”。下游节点可能只关心它是 List extends Report> 或 List extends Number>,无需知道具体是 ExcelReport 还是 PdfReport。
- 返回类型声明为 List extends Report>,调用方可直接赋值给 List
、List 变量,也可遍历为 Report 类型使用 - 禁止在该集合中 add(new PdfReport()) —— 编译器无法确认实际构造类型是否匹配,只允许 add(null)
- 若需构建新集合,应在脚本内部用具体类型(如 new ArrayList
())完成,再以 ? extends Report 包装返回
流转链路:输入与输出成对设计,形成类型安全管道
典型场景如「表单提交 → 脚本校验 → 列表渲染」。此时脚本组件的签名应体现双向兼容:
- public
void process(List super T> inputs, List extends T> outputs) - 上游可传 List
,下游可接 List (假设二者同属 Order 抽象) - 脚本内部用 T 做统一处理,不暴露具体实现类,也不强依赖继承深度
- 平台 SDK 在生成组件代理时,自动桥接泛型约束,避免开发者手动 cast
平台级红线配置建议
低代码平台可在组件元数据中固化 PECS 约束,而非依赖开发者手写泛型:
- 输入字段配置项增加「消费类型」下拉:选 Person → 自动生成 List super Person> 参数声明
- 输出字段配置项增加「产出类型」下拉:选 Report → 自动生成 List extends Report> 返回类型
- IDE 插件实时检测:若输入端口用了 ? extends、或输出端口用了 ? super,标黄警告并提示“违反PECS角色”
- 运行时沙箱拦截:对输出集合执行 add() 操作时,若底层为 ? extends,抛出 UnsupportedOperationException 并附清晰错误码(如 ERR_PECS_OUTPUT_MUTATION)










