В Twitter Эффективные Scala - псевдонимы типов, они говорят:
Не используйте подклассы, когда будет выполняться псевдоним.
trait SocketFactory extends (SocketAddress => Socket)
a SocketFactory - это функция, которая создает Socket. Использование типа псевдоним
type SocketFactory = SocketAddress => Socket
лучше. Теперь мы можем предоставить функциональные литералы для значений типа SocketFactory, а также использовать функциональный состав: val addrToInet: SocketAddress = > Long val inetToSocket: Long = > Socket
val factory: SocketFactory = addrToInet andThen inetToSocket
Обратите внимание, что псевдонимы типов не являются новыми типами - они эквивалентны синтаксической замене псевдониму имени для его типа.
Мы говорим о том, что:
trait Base
trait T1 extends Base // subclassing
type T2 = Base // type alias
Очевидно, вы не можете использовать псевдоним типа в качестве замены, когда класс/свойство имеет тело или хранит информацию.
Таким образом, использование псевдонимов типов (T2), а не расширение с помощью признака или класса (T1), имеет следующие преимущества:
- Как говорится выше, мы можем создавать функциональные литералы.
- Мы не будем создавать файл .class, для компилятора будет меньше (теоретически).
Однако он имеет следующие недостатки:
- Чтобы быть доступным в том же пространстве имен (пакет), вам необходимо определить тип в объекте пакета, который, вероятно, будет находиться в другом файле с сайта-пользователя.
- Вы не можете перетащить 'Open Type' ctrl-shift-T в псевдоним в Eclipse, но вы можете открыть декларацию (F3) в Eclipse. Вероятно, это будет исправлено в будущем.
- Вы не можете использовать псевдоним типа с другого языка, например Java.
- Если псевдоним типа параметризуется, стирание предотвращает совпадение шаблона с тем же способом, что и для признаков.
Четвертый пункт является самым серьезным для меня:
trait T1[T]
trait T2 extends T1[Any]
type T3 = T1[Any]
class C2 extends T2
val c = new C2
println("" + (c match { case t: T3 => "T3"; case _ => "any" }))
println("" + (c match { case t: T2 => "T2"; case _ => "any" }))
Это дает:
T3
T2
Компилятор дает предупреждение о первом совпадении шаблонов, которое явно не работает должным образом.
Итак, наконец, вопрос. Существуют ли другие преимущества или недостатки использования псевдонимов типов, а не расширения признака/класса?