Это иногда называет тип самостоятельной (не следует путать с явно типизированными автомодельными ссылками Scala), и это, как правило, используется для того, чтобы иметь сигнатуры методов, которые достаточно сильны, чтобы выразить, что метод работает с объектами того же типа, что и приемник.
Давайте рассмотрим пример. Скажем, у вас есть базовый признак Animal
с общим методом breed
, который принимает еще Animal
и возвращает Animal
.
trait Animal {
def breed(a: Animal): Animal
}
Хорошо, но то, что вы на самом деле хотите это breed
метод, который выражает, что каждое конкретное животное размножается только с животными одного и того же класса, а также возвращает животное одного и того же класса. Следующая реализация
class Cow extends Animal {
def breed(c: Cow) = new Cow
}
не представляется возможным, потому что подпись это breed
«s не соответствует. Переопределение также невозможно, потому что вам нужно будет изменить тип аргумента ковариантно, что запрещено.
Self-типа к спасению:
trait Animal[A <: Animal[A]] {
def breed(a: A): A
}
class Cow extends Animal[Cow] {
def breed(c: Cow) = new Cow
}
Как EECOLOR уже отмечалось, теория типа позади него называется F-ограниченный полиморфизм.
F-ограниченный полиморфизм ... да, я бы никогда не смог это найти. Спасибо, мне кажется, я понял это сейчас. –
Где вы используете 'extends' в последней строке, вы имели в виду' <: '? – AmigoNico
Я прыгал взад-вперед, чтобы выбрать один из двух. Как вы думаете, '<:' было бы лучше? – EECOLOR