【发布时间】:2011-03-16 07:36:31
【问题描述】:
我想要实现的是有一个适当的实现
def dynamix[A, B](a: A): A with B
我可能知道 B 是什么,但不知道 A 是什么(但如果 B 具有 self 类型,那么我可以在 A 上添加一些约束)。 scala 编译器对上面的签名很满意,但我还不能弄清楚实现的样子——如果有可能的话。
我想到的一些选项:
- 使用反射/动态代理。
- 最简单的情况:A 是 Java 级别的接口 + 我可以实例化 B 并且它没有自身类型。我想这不会太难(除非我遇到一些令人讨厌的、意想不到的问题):
创建一个新的 B (b),以及一个实现 A 和 B 并使用委托给 a 或 b 的调用处理程序的代理。 - 如果 B 不能被实例化,我仍然可以创建它的子类,并按照上面的描述进行操作。如果它也有 self 类型,我可能需要在这里和那里进行一些委托,但它仍然可以工作。
- 但是如果 A 是一个具体类型,而我找不到合适的接口呢?
- 是否会遇到更多问题(例如,与线性化相关的问题,或有助于 Java 互操作性的特殊结构)?
- 最简单的情况:A 是 Java 级别的接口 + 我可以实例化 B 并且它没有自身类型。我想这不会太难(除非我遇到一些令人讨厌的、意想不到的问题):
- 使用一种包装而不是 mixin 并返回 B[A],可以从 b 访问 a。
不幸的是,在这种情况下,调用者需要知道嵌套是如何完成的,如果混合/包装多次完成(D[C[B[A]]]),这可能会非常不方便,因为它需要找到正确的嵌套级别来访问所需的功能,所以我不认为这是一个解决方案。 - 实现编译器插件。我对它的经验为零,但我的直觉是它不会是微不足道的。我认为 Kevin Wright 的 autoproxy 插件的目标有点相似,但这还不足以解决我的问题(还没有?)。
您还有其他可行的想法吗?你会推荐哪种方式?期待什么样的“挑战”?
还是我应该忘记它,因为当前的 Scala 约束是不可能的?
我的问题背后的意图:
假设我有一个业务工作流程,但它并不太严格。有些步骤有固定的顺序,但有些则没有,但最后都必须完成(或者其中一些需要进一步处理)。
一个更具体的例子:我有一个 A,我可以添加 B 和 C。我不在乎先完成哪个,但最后我需要一个 A 和 B 和 C。
评论:我对 Groovy 了解不多,但突然出现了this question,我猜它或多或少与我想要的相同,至少是概念性的。
【问题讨论】:
-
另一种方法(没有经过足够深思熟虑以知道是否可行):包裹在
Dynamix[A,B](或嵌套Dynamix[A,Dynamix[B,C]])中并通过隐式展开以认知卸载客户端代码。必须定义每个嵌套深度(没有任意深度)。缺点:不会强制执行自类型约束或允许通过自类型进行跨类型交互。 -
+1 是个不错的技巧,但我觉得我仍然至少会遇到一个问题:如何指定最后我想要一个 A 和 B 和 C 或 Dynamix[A ,Dynamix[B,C]] 但我不在乎混合顺序?我也会对 Dynamix[A,Dynamix[C,B]] 感到满意,而且我认为提出这样的约束不会太容易(尤其是要混入许多特征)。不过,我喜欢你的评论,谢谢。
-
@om-nom-nom:最坏的情况,相反,但两年后答案发生了变化(例如,添加了反射)。