Scala constructor overload?

135

Bagaimana Anda menyediakan konstruktor kelebihan beban di Scala?

Landon Kuhn
sumber

Jawaban:

186

Perlu disebutkan secara eksplisit bahwa Konstruktor Tambahan di Scala harus memanggil jawaban konstruktor utama (seperti pada landon9720), atau konstruktor bantu lain dari kelas yang sama, sebagai tindakan pertama mereka. Mereka tidak bisa begitu saja memanggil konstruktor superclass secara eksplisit atau implisit seperti yang mereka dapat di Jawa. Ini memastikan bahwa konstruktor utama adalah satu-satunya titik masuk ke kelas.

class Foo(x: Int, y: Int, z: String) {  
  // default y parameter to 0  
  def this(x: Int, z: String) = this(x, 0, z)   
  // default x & y parameters to 0
  // calls previous auxiliary constructor which calls the primary constructor  
  def this(z: String) = this(0, z);   
}
Jon McAuliffe
sumber
@ Jon McAuliffe: Contoh buruk? Tanpa konstruktor kedua dan ketiga, pengguna masih dapat menelepon new Foo(x=2,z=4)dan new Foo(z=5)jika Anda mengubah baris pertama Anda keclass Foo(x: Int = 0, y: Int = 0, z: String) {
user2987828
Argumen Bernama / Default tidak tiba sampai Scala 2.8.
Jon McAuliffe
2
Perlu disebutkan bagaimana menggunakan konstruktor yang berlebihan. Bukan sepele bahwa newkata kunci diperlukan bahkan untuk kelas kasus.
Readren
33
 class Foo(x: Int, y: Int) {
     def this(x: Int) = this(x, 0) // default y parameter to 0
 }
Landon Kuhn
sumber
16

Pada Scala 2.8.0 Anda juga dapat memiliki nilai default untuk parameter konstruktor dan metode. Seperti ini

scala> class Foo(x:Int, y:Int = 0, z:Int=0) {                           
     | override def toString() = { "Foo(" + x + ", " + y + ", " + z + ")" }
     | }
defined class Foo

scala> new Foo(1, 2, 3)                                                    
res0: Foo = Foo(1, 2, 3)

scala> new Foo(4)                                                          
res1: Foo = Foo(4, 0, 0)

Parameter dengan nilai default harus datang setelah yang tanpa nilai default dalam daftar parameter.

Jörgen Lundberg
sumber
3
Ini tidak bekerja untuk standar non-sepele. jadi class Foo(val x:Int, y:Int=2*x)tidak bekerja.
subsub
@ Jörgen Lundberg: Anda menulis Parameter dengan nilai default harus datang setelah yang tanpa nilai default dalam daftar parameter. Itu salah, new Foo(x=2,z=4)akan dicetak Foo(2,0,4).
user2987828
@ user2987828 yang saya maksud adalah Anda tidak dapat menulis Foo baru (12, x = 2) Anda harus menulis Foo baru (x = 2, 12). Anda dapat menulis Foo baru (12, y = 2), maka Anda akan mendapatkan Foo (12, 2, 0)
Jörgen Lundberg
10

Sambil melihat kode saya, saya tiba-tiba menyadari bahwa saya melakukan overload pada konstruktor. Saya kemudian ingat pertanyaan itu dan kembali untuk memberikan jawaban lain:

Di Scala, Anda tidak bisa membebani konstruktor, tetapi Anda bisa melakukan ini dengan fungsi.

Juga, banyak yang memilih untuk menjadikan applyfungsi objek pendamping sebagai pabrik untuk kelas masing-masing.

Membuat kelas ini abstrak dan membebani applyfungsi untuk mengimplementasikan-instantiate kelas ini, Anda memiliki "konstruktor" kelebihan beban Anda:

abstract class Expectation[T] extends BooleanStatement {
    val expected: Seq[T]}

object Expectation {
    def apply[T](expd:     T ): Expectation[T] = new Expectation[T] {val expected = List(expd)}
    def apply[T](expd: Seq[T]): Expectation[T] = new Expectation[T] {val expected =      expd }

    def main(args: Array[String]): Unit = {
        val expectTrueness = Expectation(true)}
}

Perhatikan bahwa saya secara eksplisit menentukan masing apply- masing untuk kembali Expectation[T], jika tidak maka akan mengembalikan bebek yang diketik Expectation[T]{val expected: List[T]}.

domba terbang
sumber
0

Coba ini

class A(x: Int, y: Int) {
  def this(x: Int) = this(x, x)
  def this() = this(1)
  override def toString() = "x=" + x + " y=" + y
  class B(a: Int, b: Int, c: String) {
    def this(str: String) = this(x, y, str)
    override def toString() =
      "x=" + x + " y=" + y + " a=" + a + " b=" + b + " c=" + c
  }
}
anish
sumber