反向继承

时间:2014-03-19 21:04:36

标签: scala inheritance types

对于自定义DSL,我有一组数据生产者和消费者。 (它实际上比这复杂一点,但这足以设置问题。)用户设置一个消费者,这可能需要某种类型的数据。我想确保类型系统强制将正确类型的数据发送给正确的消费者。

数据的可能详细说明是有限的,因为可以编写一个至少可以填写合理默认值的单个数据生成器。因此,对于由默认数据供应商组成的所有数据类型应该存在下限。此外,所有数据都具有某些特征,因此应该有一个上限。数据可以通过保持特定消费者适用性的方式进行操作,或者扩大对更多消费者的适用性。因此,类型应该类似于

AllData <: D <: AnyData

在Scala中编码此约束的最简单且最优雅的方法是什么,假设我实际上并不想要AllData扩展所有其他数据类型D

现在我只有一个看起来像

的超类
class AnyData {
  def foo: Int => String = defaultIntToStringImpl
  def mapFoo(oo: String => String) = AllData((foo _) andThen oo)
}

和子类可以覆盖它

class LiteralNumberData extends AnyData {
  override val foo = (i: Int) => i.toString
}

并且有一个案例类允许每个方法都可插入

case class AllData(override val foo: Int => String) {}

但是,如果消费者要允许映射,那么消费者真的只能在AnyDataAllData之间进行选择,因为映射都会以AllData结尾。这对消费者来说并不像我想的那样提供那么多安全,而且我要确保记得不要做任何事情。 LiteralNumberData无法打包到AllData

1 个答案:

答案 0 :(得分:2)

我会对类型进行约束,如下所示:

 trait ProdConsConstraint[Producer,Consumer]{
   type Output <: AnyData
 }

如果我正确地跟着你。然后,您可以使用依赖类型来强制您正在使用的类型的适用性。

 def foo(prod: Producer, con: Consumer)(implicit ev:ProdConsConstraint[Producer,Consuer]): ev.Output = ???

这样就不需要下限了,同时也允许你有空间来打开&#34;打开&#34;通过隐式参数的范围确定。

嗯......听起来太复杂了。也许我不能充分理解这个问题。