2017-06-12 4 views
4

Lassen Sie uns sagen, dass ich eine Eigenschaft habenMuss ich die Typabweichung in Subtypen angeben?

sealed trait Expr[-InT, +OutT] { 
    def apply(lhs: InT): OutT 
} 

Ich möchte einen Subtyp And kontra in InT erstellen. Muss ich es wie folgt implementieren (1):

type BExpr[-InT] = Expr[InT, Boolean] 

final case class And[-InT](exp: BExpr[InT], exps: BExpr[InT]*) extends BExpr[InT] { 
    def apply(lhs: InT) = exps.foldLeft(exp.apply(lhs))(_ & _(lhs)) 
} 

Oder ist das Folgende genug (2)?

type BExpr[InT] = Expr[InT, Boolean] 

final case class And[InT](exp: BExpr[InT], exps: BExpr[InT]*) extends BExpr[InT] { 
    def apply(lhs: InT) = exps.foldLeft(exp.apply(lhs))(_ & _(lhs)) 
} 

Dank

+0

Ich glaube nicht, dass Sie auch Varianten zu Subtypen hinzufügen müssen. Variablen geben die Korrelation zwischen Subtypen und Supertypen an. – Sakalya

+0

dachte ich auch. Aber beide Syntaxen sind anscheinend gültig, also bin ich verwirrt. – Midiparse

+0

Beide Syntaxen sind gültig. Wenn Sie den Subtyp als [-Int] definieren, wird er für seine Unterklassen invariant. – Sakalya

Antwort

3

Nun, lassen Sie uns einen kleinen Test machen.

scala> trait A[+T] 
defined trait A 

scala> trait B[T] extends A[T] 
defined trait B 

scala> def b1: B[String] = ??? 
b1: B[String] 

scala> def b2: B[AnyRef] = b1 
<console>:13: error: type mismatch; 
found : B[String] 
required: B[AnyRef] 
Note: String <: AnyRef, but trait B is invariant in type T. 
You may wish to define T as +T instead. (SLS 4.5) 
     def b2: B[AnyRef] = b1 
         ^

scala> def a: A[AnyRef] = b1 
a: A[AnyRef] 

scala> trait B[+T] extends A[T] 
defined trait B 

scala> def b3: B[String] = ??? 
b3: B[String] 

scala> def b4: B[AnyRef] = b3 
b4: B[AnyRef] 

Also ja, es macht einen Unterschied. Wenn Sie den Subtyp der Welt zugänglich machen möchten und nicht zu einer privaten internen Implementierung, ist es wahrscheinlich besser, die entsprechenden Varianzanmerkungen hinzuzufügen.

Verwandte Themen