Разница между наследованием признаков и аннотацией типа
В Scala я видел конструкции
trait T extends S
и
trait T { this: S =>
используется для достижения аналогичных вещей (а именно, что абстрактные методы в S
должны быть определены до создания экземпляра). Какая разница между ними? Почему вы используете один над другим?
Ответы
Ответ 1
Я бы использовал self-types для управления зависимостями: эта черта требует смешения другого признака. И я бы использовал наследование для уточнения другого признака или интерфейса.
Как пример:
trait FooService
trait FooRemoting { this : FooService => }
trait FooPersistence { this : FooService => }
object Services extends FooService with FooRemoting with FooPersistence
Теперь, если FooRemoting и FooPersistence оба унаследовали бы от FooService, а у FooService есть члены и методы, как бы выглядели бы службы?
Если для наследования у нас будет что-то вроде:
trait Iterator[T] {
def hasNext : boolean
def next : T
}
trait InfiniteIterator[T] extends Iterator[T] {
def hasNext = true
}
Ответ 2
Аннотации типа Self позволяют вам выражать циклические зависимости. Например:
trait A extends B
trait B { self: A => }
Это невозможно с простым наследованием.
Ответ 3
Спрашивая вопрос, я столкнулся с этими сообщениями:
Спирос Цавеллас говорит об использовании признака в качестве открытого интерфейса и типа self как помощника, который должен быть смешан с классом реализации.
В заключение, если мы хотим двигаться реализация методов внутри признаков то мы рискуем загрязнить интерфейс этих черт с абстрактными методами которые поддерживают осуществление конкретные методы и не связаны с основной ответственностью черта. Решение этой проблемы переместить эти абстрактные методы в другие черты и составлять черты вместе с аннотациями типа и множественное наследование.
Например:
trait PublicInterface { this: HelperTrait =>
// Uses helperMethod
}
trait HelperTrait {
def helperMethod = // ...
}
class ImplementationClass extends PublicInterface with HelperTrait
Обзор Scala обсуждается с использованием аннотаций типа self с элементами абстрактного типа - по-видимому, не возможно extend
абстрактный элемент типа (?)
Ответ 4
Ответ - "округлость". Но не только.
Аннотации типа Self решают для меня основную проблему наследования: то, что вы наследуете, не может использовать то, что вы есть.
С типом self все становится легко.
Мой шаблон следующий и может рассматриваться как вырожденный торт:
trait A { self: X => def a = reuseme}
trait B { self: X => def b = a }
class X extends A with B { def reuseme=null }
Вы можете взорвать свой класс в нескольких типах поведения, которые могут быть вызваны из любой точки сборки, но при этом остаются чисто напечатанными.
Нет необходимости в болезненном указании слишком часто (и ошибочно), идентифицированном с шаблоном пирога.
Половина (если не совокупность) свернутых фреймворков Java DI за последние десять лет была посвящена этому, конечно, без ввода текста.
Люди, все еще использующие JAVA в этом домене, явно теряют свое время: "SCALA ouakbar".
Ответ 5
Несмотря на то, что он не отвечает на ваш вопрос, я пытался понять аннотации самонаведения и в основном потерялся в ответах, и как-то закончил велосипедную прогулку по вариациям вашего вопроса, в котором основное внимание уделяется использованию аннотаций самонастройки для определяя зависимости.
Итак, здесь я публикую описание варианта использования, в котором хорошо иллюстрируются аннотации самостоятельного типа, а именно что-то вроде безопасного типа 'this' в качестве подтипа:
http://programming-scala.labs.oreilly.com/ch13.html#SelfTypeAnnotationsAndAbstractTypeMembers
надеясь, что было бы полезно тем, кто попадает на этот вопрос случайно (и, как и я, не успел прочитать книгу scala, прежде чем начинать исследовать:-))