Konstruktor pribadi dan terlindungi di Scala

109

Saya penasaran tentang dampak tidak adanya konstruktor primer eksplisit di Scala, hanya konten badan kelas.

Secara khusus, saya menduga bahwa pola konstruktor privat atau dilindungi, yaitu, mengontrol konstruksi melalui objek pendamping atau metode kelas atau objek lain mungkin tidak memiliki implementasi yang jelas.

Apakah aku salah? Jika demikian, bagaimana caranya?

Don Mackenzie
sumber
Anda bisa memiliki Scala singleton (dengan kata kunci object, yaitu), dan mendefinisikan kelas Anda sebagai private dalam singleton tersebut, dan memiliki metode singleton untuk membangun objek Anda.
Paggas
@Paggas, sayangnya ketika Anda mengembalikan sebuah instance dari kelas yang ditandai privat di luar cakupannya, itu tidak akan dikompilasi, bahkan ketika dikembalikan dari metode itu dalam objek pendamping cakupan.
Don Mackenzie
Ini dilakukan cukup banyak di seluruh kode sumber Scalaz. Konsep ini juga dikenal sebagai tipe data aljabar abstrak .
Tony Morris

Jawaban:

190

Anda dapat mendeklarasikan konstruktor default sebagai private / protected dengan memasukkan kata kunci yang sesuai antara nama kelas dan daftar parameter, seperti ini:

class Foo private () { 
  /* class body goes here... */
}
Aleksander Kmetec
sumber
Terima kasih Aleksander, Bisakah Anda memberi tahu saya apakah ini disajikan di salah satu buku skala atau dalam spesifikasi bahasa? Maaf, saya belum bisa memberi suara positif.
Don Mackenzie
Saya hanya melihat sekilas penjelasan "Programming Scala" tentang konstruktor (halaman 92-95) dan saya tidak melihatnya disebutkan di sana. Sebenarnya saya menemukan jawaban atas pertanyaan Anda di changelog lama, tapi saya belum pernah melihatnya disebutkan di tempat lain sebelumnya. Tautan: scala-lang.org/node/43#2.4.0
Aleksander Kmetec
18
Pag 414 dari "Programming in Scala". Halaman 97 dari Scala Pemrograman Wampler. Halaman 60 dari Scala Pemrograman Subramaniam. Saya tidak memiliki PDF Scala Awal dengan saya sekarang untuk memeriksanya.
Daniel C. Sobral
Oh, saya melihatnya sekarang di halaman 97. Terima kasih.
Aleksander Kmetec
1
Terima kasih untuk penelitian lebih lanjut, saya mendapatkan buku Wampler, tetapi hanya di ponsel saya dan jelas belum membacanya secara menyeluruh tetapi saya telah menemukan bahwa buku itu melengkapi buku Odersky dengan sangat baik.
Don Mackenzie
64

Jawaban Aleksander benar, tetapi Pemrograman di Scala menawarkan alternatif tambahan:

sealed trait Foo {
 // interface
}

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

  private class FooImpl(...) extends Foo { ... } // real class
}
Daniel C. Sobral
sumber
18
Muncul beberapa tahun kemudian untuk mengatakan: Saya pikir ini adalah jawaban yang baik untuk pertanyaan tetapi solusi yang buruk untuk masalah tersebut. Jika beberapa programmer masa depan menggunakan kode Aleksander, dia akan berkata, "Ah, konstruktor utama adalah privat tetapi konstruktor lain tidak." Jika programmer itu melihat kode Daniel, dia akan berkata, "Ah, mereka menggunakan pola Pabrik untuk mengkompensasi ketidakmampuan Scala untuk menandai konstruktor default sebagai privat. Tunggu, Scala's dapat menandai konstruktor default sebagai privat! Apa yang terjadi disini?!?" Dengan kata lain, rasio WTF / LOC yang buruk.
Malvolio
20
@Malvolio Saya tidak setuju. Pola ini tidak hanya membuat konstruktor utama menjadi pribadi, tetapi juga implementasinya , memaksa pengguna untuk menggunakan antarmuka (sifat). Itu punya nilai tersendiri. Adapun seseorang yang memikirkan sesuatu karena dia tidak tahu bahasanya - piffle! Mengutip Kenny Tilton, pelajari bahasa sialan itu !
Daniel C. Sobral
7
Harus disebutkan di suatu tempat bahwa pendekatan ini berarti tidak menggunakan newkata kunci.
Travis Parks
1
Satu peringatan dengan pendekatan ini adalah bahwa seseorang masih dapat membuat instance Foo melalui implementasinya sendiri. Itu bisa dilihat sebagai keuntungan atau kerugian tergantung pada alasan pengendalian konstruksi.
aij
1
@aij Benar, jadi saya membuatnya jadi itu tidak bisa terjadi lagi. :)
Daniel C. Sobral