如何在Scala中混合相同特征的不同类型实例?
我想以不同的方式检查如何扩展此代码,然后在需要时将这些功能扩展混合在一起.
// Initial object algebra interface for expressions: integers and addition trait ExpAlg[E] { def lit(x : Int) : E def add(e1 : E,e2 : E) : E } // An object algebra implementing that interface (evaluation) // The evaluation interface trait Eval { def eval() : Int } // The object algebra trait EvalExpAlg extends ExpAlg[Eval] { def lit(x : Int) = new Eval() { def eval() = x } def add(e1 : Eval,e2 : Eval) = new Eval() { def eval() = e1.eval() + e2.eval() } } // Evolution 1: Adding subtraction trait SubExpAlg[E] extends ExpAlg[E] { def sub(e1 : E,e2 : E) : E } // Updating evaluation: trait EvalSubExpAlg extends EvalExpAlg with SubExpAlg[Eval] { def sub(e1 : Eval,e2 : Eval) = new Eval() { def eval() = e1.eval() - e2.eval() } } // Evolution 2: Adding pretty printing trait PPrint { def print() : String } trait PrintExpAlg extends ExpAlg[PPrint] { def lit(x: Int) = new PPrint() { def print() = x.toString() } def add(e1: PPrint,e2: PPrint) = new PPrint() { def print() = e1.print() + "+" + e2.print() } } trait PrintSubExpAlg extends PrintExpAlg with SubExpAlg[PPrint] { def sub(e1: PPrint,e2: PPrint) = new PPrint() { def print() = e1.print() + "-" + e2.print() } } object OA extends App { trait Test extends EvalSubExpAlg with PrintSubExpAlg //error } 目前我收到的错误是: 我怎么能把两个类型的Eval和PPint放在一个“帽子”下才能被认为是来自同一家族的类型,或者不是一个正确的解决方案,而我可能在两种类型的成员之间存在冲突的继承呢? 编辑 我改变了它,如下所示: // Initial object algebra interface for expressions: integers and addition trait ExpAlg { type Opr <: Operations def lit(x : Int) : Opr def add(e1 : Opr,e2 : Opr) : Opr } // An object algebra implementing that interface (evaluation) // The evaluation interface trait Eval extends Operations { def eval() : Int } // The object algebra trait EvalExpAlg extends ExpAlg { type Opr = Eval def lit(x : Int) = new Eval() { def eval() = x } def add(e1 : Eval,e2 : Eval) = new Eval() { def eval() = e1.eval() + e2.eval() } } // Evolution 1: Adding subtraction trait SubExpAlg extends ExpAlg { def sub(e1 : Opr,e2 : Opr) : Opr } // Updating evaluation: trait EvalSubExpAlg extends EvalExpAlg with SubExpAlg { def sub(e1 : Eval,e2 : Eval) = new Eval() { def eval() = e1.eval() - e2.eval() } } // Evolution 2: Adding pretty printing trait PPrint extends Operations { def print() : String } trait PrintExpAlg extends ExpAlg { type Opr = PPrint def lit(x: Int) = new PPrint() { def print() = x.toString() } def add(e1: PPrint,e2: PPrint) = new PPrint() { def print() = e1.print() + "+" + e2.print() } } trait PrintSubExpAlg extends PrintExpAlg with SubExpAlg { def sub(e1: PPrint,e2: PPrint) = new PPrint() { def print() = e1.print() + "-" + e2.print() } } object OA extends App { class Test extends EvalSubExpAlg class Test2 extends PrintSubExpAlg val evaluate = new Test val print = new Test2 val l1 = evaluate.lit(5) val l2 = evaluate.lit(4) val add1 = evaluate.add(l1,l2).eval() val print1 = print.add(print.lit(5),print.lit(4)).print() println(print1) println(add1) } 我唯一要问的可能是只使用一个Test类并在两种类型的方法之间导航(通过引用这些类型). 解决方法
让我们简化它:
trait Z {val a = 5} trait K {val a = 6} trait A[T] { def aa: T} trait A1 extends A[Z] { def aa = new Z{}} trait A2 extends A[K] { def aa = new K{}} scala> class C extends A1 with A2 <console>:12: error: illegal inheritance; class C inherits different type instances of trait A: A[K] and A[Z] 那么,当你这么做时,你期望被称为什么(新的C).aa?如果你真的不在乎,只想访问C里面的那些: trait A {type T; protected def aa: T} trait A1 extends A {type T >: Z; protected def aa = new Z{}} trait A2 extends A {type T >: K; protected def aa = new K{}} scala> class C extends A1 with A2 { override type T = Any override protected def aa = ??? def bbb:Z = super[A1].aa def zzz:K = super[A2].aa } 但我建议选择一些默认方法并从Z继承Z或从Z继承Z,为C#aa提供正常的默认实现.一般来说,这里的问题是scala中的traits适用于mixin和polymorphism,所以你不能只关闭他们的外部世界成员(由于Liskov-Substitution),即使你实际上并不需要自动强制转换为超类型.有关详情,请参见related question. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |