5

特定の型をより一般的な構造型に適合させる問題に興味があります。次の例を検討してください。

trait Sup

trait Sub extends Sup

type General = {
   def contra(o: Sub): Unit
   def co(): Sup
   def defaults(age: Int): Unit
   def defaults2(age: Int): Unit
   def defaults3(first: String): Unit
} 

trait Specific {
   def contra(o: Sup): Unit // doesn't conform
   def co(): Sub // conforms
   def defaults(age: Int, name: String = ""): Unit // doesn't conform
   def defaults2(name: String = "", age: Int = 0): Unit // doesn't conform
   def defaults3(first: String = "", last: String = ""): Unit // doesn't conform
}

非準拠のケースのそれぞれで、 のメソッドへの呼び出しはGeneral、 の対応するメソッドに安全に解決できますSpecificこの質問には、より興味深い実際の例があります。

trait Versionable[T] {
   self: { def copy(version: Int): T } =>
   val version = 0
   def incrementVersion = copy(version = version + 1)
}

case class Customer(name: String, override val version: Int) 
      extends Versionable[Customer] {
   def changeName(newName: String) = copy(name = newName)
}

ここで、Customer のcopyメソッドは、Versionable の自己型アノテーションの署名に準拠していません。ただし、コンパイラで許可されている場合は、 とcopy同じように呼び出すことができることに注意してくださいVersionable.incrementVersion。明らかに、Customer のメソッドの実際の署名は、オプションでパラメーターを指定copyできるという無関係な知識を持っているため、Versionable で使用するにはあまりにも具体的です。name

これらの制限を回避する方法はありますか? そのような一般化された適合が悪い考えになる理由はありますか?

4

1 に答える 1

1

1 つの懸念事項は、このコードを読むときに次のことです。

self: { def copy(version: Int): T }

次の例のように、パラメーターの名前が重要であるとは思わないでください。

case class Robot(number: Int, override val version: Int)
  extends Versionable[Robot]

編集:別のメモでは、メソッドのパラメーターの反変性の欠如に関して、次のことができます。

type General = { val contra: (Sub => Unit) }
class B { val contra = ((o:Sup) => println(o)) }
var b:General = new B
于 2010-08-31T13:40:01.910 に答える