2014-01-03 2 views
3

Можно ли переопределить val s или def s в конструкторе подкласса? Я хочу инициализировать (или установить) элементы признака или абстрактные члены класса в конструкторе подкласса как параметры .Scala: Можно ли переопределить val в конструкторе подкласса?

Ниже приведен пример.

 
trait A { 
    def memberDef: Int => String 
    val memberVal: String 
} 

class B(
    override val memberDef: Int => String, 
    override val memberVal: String) 
    extends A { 
    ... 
} 

Здесь class B 'S memberDef переопределяет trait A' s memberDef и class B 'S memberVal переопределяет trait A' s memberVal.

Когда я скомпилировал это, ошибки не было. Тем не менее, я хочу знать, есть ли какие-либо ошибки в этой реализации, или если есть лучшая реализация.

ответ

3

Ответ на заголовок сообщения - да. По большей части.

Трудно сказать, что может быть «лучшей» реализацией, поскольку я не знаю, что вы пытаетесь выполнить с помощью этого кода (помимо доказательства концепции). Но есть две вещи, которые следует учитывать.

В целом вы не нуждаетесь в признаке с val. Есть сложные, хорошо документированные проблемы инициализации, решаемые только с использованием lazy val или def на уровне признаков. Кроме того, хотя def в признаке может быть реализован def, val, lazy val или object, val в признаке может быть реализован только val. Таким образом, там гораздо меньше гибкости.

Другая вещь, которую следует учитывать, - это не синтаксис Scala, а более общий дизайн объекта. Я знаю, что ваш пример надуман, но просто имейте в виду, что вы создали нечеткую абстракцию, предоставив вызывающему пользователю способ изменить публичный API B. Утечка абстракций никогда не бывает хорошей.

5

Я хотел бы добавить еще один из возможных решений с использованием ранних инициализаторами:

class B(memberDefParam: Int => String, memberValParam: String) extends { 
    val memberVal: String = memberValParam 
} with A { 
    val memberDef: Int => String = memberDefParam 
} 

Я хотел бы использовать это, потому что Одерски сказал, что если вы используете ранние инициализаторами вы достигли Святой Грааль - Уровень L3: Эксперт библиотека Дизайнер: http://www.scala-lang.org/old/node/8610

Кстати, переопределение общедоступного метода с помощью функции, предоставляемой как аргумент конструктора, совсем не выглядит для меня приятным, но это уже другая история.

+0

Это довольно умно. – Vidya

+1

«Я бы использовал это, потому что Мартин Одерский сказал, что если вы используете ранние инициализаторы, вы достигли святого Грааля - Level L3: Дизайнер библиотеки экспертов: http://www.scala-lang.org/old/node/8610« Я », d сказать, что это прямо противоположно его значению. Дизайнер экспертной библиотеки должен понимать _why_ и _when_ использовать эти функции, а не только как их использовать (конечно же, это относится ко всем другим уровням). –

+2

L3 действительно не святой Грааль! Если я смогу провести аналогию с дзюдо, то L3 будет вашим черным поясом. После этого у вас есть несколько dan-классов, олимпийских медалей и т. Д., К которым нужно стремиться. Подождите, пока вы не перейдете к макросам :) –

Смежные вопросы