Я следую за собой в «Программировании в Scala» Одерский в 2-е издания, а в разделе 12.5 «Признаки как наращиваемые изменения», он представляет IntQueue
наряду с чертой, которая удваивает любые значения, которые вы вставляете в очередь:Scala: Как наследовать одну и ту же черту дважды?
import scala.collection.mutable.ArrayBuffer
abstract class IntQueue {
def get(): Int
def put(x: Int)
}
class BasicIntQueue extends IntQueue {
private val buf = new ArrayBuffer[Int]
def get() = buf.remove(0)
def put(x: Int) { buf += x }
}
trait Doubling extends IntQueue {
abstract override def put(x: Int) {
super.put(2 * x)
}
}
Книга затем показывает, что вы можете создать экземпляр очереди, которая удваивает каждое целое число, которое вы вставляете в него через new BasicIntQueue with Doubling
. То, что я хотел сделать, было создано аналогичной очереди, которая умножает каждое целое число на 4, например: new BasicIntQueue with Doubling with Doubling
. Однако это вызывает ошибку компиляции «trait Doubling is inherited twice
». Взглянув в это, я полагаю, что это имеет какое-то отношение к ограничениям линейности; в частности, что данный признак не может появляться дважды в линейной иерархии классов.
Каков наилучший способ для достижения эффекта, который я хочу?
Вот немного больше информации о моем «реальном мире» прецеденте, в случае ответ зависит от этого:
У меня есть класс SoundFile
, который считывает файл .wav, и дает SoundFile
объект, который расширяет черту WaveForm
. Класс SoundFile
аналогичен приведенному выше значению BasicIntQueue
, а признак WaveForm
аналогичен приведенному выше IntQueue
.
У меня есть 2 элемента, которые аналогичны Doubling
, один из которых называется Echo
, а один - Reverse
.
Я хотел написать new SoundFile("myFile.wav") with Reverse with Echo with Reverse
, но я столкнулся с той же ошибкой компиляции о наследовании от черты Reverse
дважды.
Есть ли у JVM это ограничение? Java делает; ни один класс не может реализовать один и тот же интерфейс дважды. –
Я бы не удивился, если бы у JVM было это ограничение, но, не зная подробностей о том, как Scala реализует множество функций на JVM, я не понимаю, почему Scala не может генерировать байт-код, который «делает правильную вещь», , E.g. Если вы спросите, был ли этот анонимный класс экземпляром 'Doubling', он ответил бы' true', потому что это правда; не нужно делать тот факт, что он наследует два раза в системе типов. –
Интересный вопрос. Подчеркивает, что черты менее «слои» и больше «mixin». Черты не являются обертками, не являются «функцией, применяемой к классу/интерфейсу для создания нового класса/интерфейса». –