Me interesa el problema de conformar un tipo específico a un tipo estructural más general. Consideremos los siguientes ejemplos:Conformidad de tipo estructural generalizada en Scala
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
}
En cada uno de los casos no conformes, una llamada al método en General
de forma segura se puede resolver con el método correspondiente en Specific
. Un ejemplo práctico más interesante se puede encontrar en this question:
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)
}
Aquí, el método del Cliente copy
no se ajusta a la firma en el tipo de auto anotación de versionable. Sin embargo, tenga en cuenta que, si el compilador lo permite, puede invocarse copy
tal como está en Versionable.incrementVersion
. Claramente, la firma real del método copy
del Cliente es demasiado específica para su uso en Versionable, ya que tiene el conocimiento irrelevante de que uno puede suministrar opcionalmente un parámetro name
.
¿Hay formas de evitar estas limitaciones? ¿Hay razones por las cuales esa conformidad generalizada sería una mala idea?
Otro ejemplo práctico: http://stackoverflow.com/questions/4410469/refactoring-copy-functionality –