Если типы не совсем одинаковые, как работает этот DeepCopy2?
Это довольно просто.Это работает, потому что нет вовлеченного полиморфизма.Статически известно, что ConcreteType2
имеет deepCopy()
метод, который возвращает ConcreteType2
.Вы даже можете удалить type ThisType
из всей иерархии, и все равно будет работать так же.
Но как же тогда я могу использовать преимущества F-ограниченных типов, если F-ограниченныйтип не совсем совпадает с типом, использующим F-ограниченный тип?
Вам нужно сообщить компилятору, что он такой же, как вы не указали достаточно.Давайте посмотрим на пример, который работает и является полиморфным:
def deepCopy[A <: FType { type ThisType = A }](_type: A): A = _type.deepCopy()
// ^ --important bit-- ^
Это определяет метод, который работает для любого A
, то есть FType
, а также для его члена типа ThisType
установлено значение A
, связывая их вместе.Это означает, что это будет работать для ваших определений ConcreteType
и ConcreteType2
.Однако он НЕ будет компилироваться для классов, которые не определены должным образом, таких как этот:
class Bogus extends FType {
override type ThisType = ConcreteType2
override def deepCopy(): ConcreteType2 = new ConcreteType2
}
deepCopy(new Bogus)
В качестве альтернативы, давайте начнем с немного измененной версии вашего метода:
def deepCopyPD[A <: FType](_type: A): _type.ThisType = _type.deepCopy()
^path-dependent^
Это не накладывает никаких ограничений на ThisType
, но на самом деле компилятор мог бы вывести правильные версии этого для всех случаев:
val x: ConcreteType2 = deepCopyPD(new ConcreteType2)
val y: ConcreteType2 = deepCopyPD(new Bogus) // yep, this invocation is possible with such signature
Однако, также возможно дальнейшее добавление ограниченийиспользование доказательства равенства типов в качестве неявного параметра:
def deepCopyPD2[A <: FType](_type: A)(implicit ev: _type.ThisType =:= A): A = _type.deepCopy()
Это, опять же, запрещает вызов с Bogus