Черты в Scala могут использоваться как как микшины, так и интерфейсы. Это приводит к некоторой непоследовательности - если я хочу, чтобы закрыть какой-то метод внутри черта, я просто не могу это сделать:инкапсуляция для элементов mixin в Scala
object Library {
protected trait A { def a: Int = 5 }
trait B extends A { private override def a: Int = super.a }
//I want to close `a` memeber for all traits extending B; it's still possible to open it in some another trait `C extends A`, or even `Z extends B with C`
}
// Exiting paste mode, now interpreting.
<console>:10: error: overriding method a in trait A of type => Int;
method a has weaker access privileges; it should not be private
trait B extends A { private override def a: Int = super.a }
^
Такая ошибка совершенно отлично от LSP -perspective как я (или компилятор) может хотеть бросить это супертип A
. Но если я просто использую его в качестве микширования, мне никогда не нужно делать это на самом деле, например, в некоторых вариантах Cake-pattern. Я сделаю что-то вроде:
import Library._
object O extends B with K with L with App
и все. Я даже не могу получить доступ к значению A
. Я знаю, есть тип вывода, который может перейти к супертипу, но это всего лишь «строка типов», поэтому компилятор мог просто пропустить здесь A
и продолжать (конечно, очень теоретично). Другой пример - here Мне пришлось предоставить стандартную реализацию метода, который мне действительно не нужен.
В настоящее время я использую OOP-состав, но он не настолько гибкий (поскольку линеаризация здесь не работает) и не очень совместима с концепцией mix-ins. Некоторые проекты, которые я видел, на самом деле делают mixins и имеют «over9000» redundand visible members. Несколько лет назад появилась идея «маркировать» такой состав mixins на with
ключевое слово, заданное вместо extends
, но даже не могу найти этот поток сейчас.
Итак, есть ли какие-либо улучшения для инкапсуляции ad-hoc-членов?