特定の型をより一般的な構造型に適合させる問題に興味があります。次の例を検討してください。
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
これらの制限を回避する方法はありますか? そのような一般化された適合が悪い考えになる理由はありますか?