Приватний і захищений конструктор у Scala


109

Мені було цікаво вплинути на те, що у Scala немає явного первинного конструктора, а лише вмісту тіла класу.

Зокрема, я підозрюю, що модель приватного або захищеного конструктора, тобто керування конструкцією за допомогою супутнього об'єкта чи методів іншого класу чи об'єкта, може не мати очевидного втілення.

Я помиляюся? Якщо так, то як це робиться?


Ви можете мати одиночну шкалу Scala (з ключовим словом об'єкта, тобто) та визначити свій клас як приватний в межах цього сингтона та мати методи синглів для побудови ваших об'єктів.
Паггас

@Paggas, на жаль, коли ви повертаєте екземпляр класу, позначеного приватним, поза його областю, він не буде компілюватися, навіть коли повертається з методу, який знаходиться в об'єкті супутника області.
Дон Макензі

Це робиться досить рясно у всьому вихідному коді Scalaz. Поняття також відоме як абстрактний алгебраїчний тип даних.
Тоні Морріс

Відповіді:


190

Ви можете оголосити конструктор за замовчуванням як приватний / захищений, вставивши відповідне ключове слово між назвою класу та списком параметрів, таким як:

class Foo private () { 
  /* class body goes here... */
}

Дякую, Олександре, чи можете ви сказати, будь ласка, чи це представлено в одній із книг "Скала" чи в мовній специфікації? Вибачте, я ще не можу подати заявку.
Дон Маккензі

Я просто переглянув конструктори "програмування Scala" (стор. 92-95), і не бачу, щоб це там було згадано. Насправді я знайшов відповідь на ваше запитання у старому журналі змін, але раніше ніколи не бачив його. Посилання: scala-lang.org/node/43#2.4.0
Aleksander Kmetec

18
Паг. 414 "Програмування в Scala". Сторінка 97 програми масштабування програми Wampler. Сторінка 60 програми Scala програмування Subramaniam. Зараз у мене немає PDF-файлу «Початок Scala», щоб перевірити його.
Даніель К. Собрал

О, я бачу це зараз на сторінці 97. Дякую.
Олександр Кметек

1
Дякую обом для подальших досліджень, я отримав книгу Wampler, але лише на своєму телефоні і, очевидно, не прочитав її досконало, але я виявив, що вона доповнює Одерського книгу на диво добре.
Дон Макензі

64

Відповідь Олександра правильна, але програмування в Scala пропонує додаткову альтернативу:

sealed trait Foo {
 // interface
}

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

  private class FooImpl(...) extends Foo { ... } // real class
}

18
Спустіть через роки, щоб сказати: Я думаю, що це хороша відповідь на питання, але поганий варіант вирішення проблеми. Якби якийсь майбутній програміст мав код Олександра, він би сказав: "Ах, основний конструктор приватний, але інші конструктори - ні". Якби той програміст подивився на код Даніеля, він би сказав: "Ах, вони використовують заводський зразок, щоб компенсувати неможливість Scala позначити конструктори за замовчуванням як приватні. Зачекайте, Scala може позначити конструктори за замовчуванням як приватні! Що відбувається" тут?!? " Іншими словами, неправильне співвідношення WTF / LOC.
Мальволіо

20
@Malvolio Я не зовсім згоден. Ця закономірність не тільки робить основний конструктор приватним, але й реалізовує , змушуючи користувача використовувати інтерфейс (рису). Це має власну цінність. Що стосується того, що хтось щось думає, тому що він / вона не знає мови - piffle! Щоб цитувати Кенні Тілтона, вивчіть прокляту мову !
Даніель К. Собрал

7
Десь слід зазначити, що такий підхід означає не використовувати newключове слово.
Travis Parks

1
Одне застереження при такому підході полягає в тому, що хтось все-таки може створити Foo шляхом власної реалізації. Це може розглядатися як перевага чи недолік залежно від причини контролю будівництва.
аїй

1
@aij Правда, тому я просто зробив це так, що більше не може трапитися. :)
Даніель К. Собрал
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.