Частный и защищенный конструктор в Scala

109

Мне было любопытно, как влияет отсутствие явного первичного конструктора в Scala, а только содержимое тела класса.

В частности, я подозреваю, что частный или защищенный шаблон конструктора, то есть управляющий построением через сопутствующий объект или другой класс или методы объекта, может не иметь очевидной реализации.

Я ошибся? Если да, то как это делается?

Дон Маккензи
источник
У вас может быть синглтон Scala (то есть с ключевым словом object), и вы можете определить свой класс как частный в этом синглтоне и иметь методы синглтона для создания ваших объектов.
Paggas
@Paggas, к сожалению, когда вы возвращаете экземпляр класса, помеченного как частный, вне его области видимости, он не компилируется, даже когда он возвращается из метода, находящегося в объекте-компаньоне области.
Don Mackenzie
Это делается довольно часто в исходном коде Scalaz. Эта концепция также известна как абстрактный алгебраический тип данных.
Тони Моррис

Ответы:

190

Вы можете объявить конструктор по умолчанию как частный / защищенный, вставив соответствующее ключевое слово между именем класса и списком параметров, например:

class Foo private () { 
  /* class body goes here... */
}
Александр Кметек
источник
Спасибо, Александр, Подскажите, пожалуйста, в одной из книг по scala или в спецификации языка это представлено? Извините, я пока не могу проголосовать.
Don Mackenzie
Я только что просмотрел объяснение конструкторов в "Programming Scala" (страницы 92-95) и не вижу, чтобы это там упоминалось. Я действительно нашел ответ на ваш вопрос в старом журнале изменений, но я никогда раньше не видел, чтобы он упоминался где-либо еще. Ссылка: scala-lang.org/node/43#2.4.0
Александр Кметек
18
Стр. 414 «Программирование на Scala». Страница 97 программы Wampler's Programming Scala. Страница 60 программы Subramaniam's Programming Scala. У меня сейчас нет PDF-файла Beginning Scala, чтобы проверить его.
Дэниел С. Собрал,
О, теперь я вижу это на странице 97. Спасибо.
Александр Кметек
1
Спасибо обоим за дальнейшие исследования, у меня есть книга Wampler, но только в телефоне, и я явно не читал ее полностью, но я обнаружил, что она на удивление хорошо дополняет книгу Одерского.
Don Mackenzie
64

Ответ Александра правильный, но Программирование на Scala предлагает дополнительную альтернативу:

sealed trait Foo {
 // interface
}

object Foo {
  def apply(...): Foo = // public constructor

  private class FooImpl(...) extends Foo { ... } // real class
}
Дэниел С. Собрал
источник
18
Годы спустя он сказал: я думаю, что это хороший ответ на вопрос, но плохое решение проблемы. Если бы какой-нибудь будущий программист обратился к коду Александра, он бы сказал: «А, первичный конструктор частный, а другие конструкторы - нет». Если бы этот программист взглянул на код Дэниела, он бы сказал: «А, они используют шаблон Factory, чтобы компенсировать неспособность Scala пометить конструкторы по умолчанию как частные. Подождите, Scala может пометить конструкторы по умолчанию как частные! Что происходит? Здесь?!?" Другими словами, плохое соотношение WTF / LOC.
Мальволио
20
@Malvolio Я не совсем согласен. Этот шаблон не только делает закрытым первичный конструктор, но и реализацию , заставляя пользователя использовать интерфейс (черта). Это имеет свою ценность. А если кто-то что-то думает, потому что не знает языка - фиг! Цитируя Кенни Тилтона, учите чертов язык !
Daniel C. Sobral
7
Следует где-то упомянуть, что этот подход означает отказ от newключевого слова.
Трэвис Паркс,
1
Одно из предостережений при таком подходе состоит в том, что кто-то все еще может создать экземпляр Foo через свою собственную реализацию. Это можно рассматривать как преимущество или недостаток в зависимости от причины контроля строительства.
aij
1
@aij Верно, поэтому я просто сделал так, чтобы этого больше не могло случиться. :)
Дэниел С. Собрал