Kata kunci "baru" di Scala

96

Saya punya pertanyaan yang sangat sederhana - kapan kita harus menerapkan kata kunci baru saat membuat objek di Scala? Apakah ketika kita mencoba untuk membuat contoh objek Java saja?

Bober02
sumber

Jawaban:

146

Gunakan newkata kunci ketika Anda ingin merujuk ke classkonstruktor milik sendiri:

class Foo { }

val f = new Foo

Abaikan newjika Anda merujuk ke metode objek pendamping apply:

class Foo { }
object Foo {
    def apply() = new Foo
}

// Both of these are legal
val f = Foo()
val f2 = new Foo

Jika Anda telah membuat kelas kasus:

case class Foo()

Scala diam-diam membuat objek pendamping untuk Anda, mengubahnya menjadi ini:

class Foo { }
object Foo {
    def apply() = new Foo
}

Jadi Anda bisa melakukannya

f = Foo()

Terakhir, perlu diingat bahwa tidak ada aturan yang mengatakan bahwa apply metode pengiring harus berupa proxy untuk konstruktor:

class Foo { }
object Foo {
    def apply() = 7
}

// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7

Dan, karena Anda menyebutkan kelas Java: ya - kelas Java jarang memiliki objek pendamping dengan sebuah applymetode, jadi Anda harus menggunakan newdan konstruktor kelas yang sebenarnya.

Owen
sumber
1
Kelas Java tidak pernah bisa memiliki objek pendamping. Itu bisa memiliki sebuah objek yang bisa bekerja sebagai Pabrik untuk kelas Java - tapi objek ini bukan objek pendampingnya.
kiritsuku
@Antoras Karena kelas Scala dikompilasi ke bytecode Java, dan dapat didistribusikan dalam bentuk terkompilasi, dapatkah Scala membedakan antara pendamping Scala yang sebenarnya dan kelas bernama Foo $ dengan anggota MODUL $ statis?
Owen
1
Saya pikir scalac dapat membedakannya karena dispesifikasi bahwa objek pendamping harus dideklarasikan dalam file yang sama dengan kelas pendampingnya. Karena "properti" pendamping hanya ada di Scala dan bukan di tingkat Bytecode, scalac harus memeriksa kode Scala dan bukan Bytecode untuk memastikan bahwa spesifikasi diikuti.
kiritsuku
1
Adakah contoh kelas Java yang TIDAK menggunakan kata kunci baru di Scala?
Bober02
Juga metode pada objek pendamping akan dibuat dapat diakses melalui metode statis di kelas juga dan itu tidak akan pernah terjadi dengan kelas-kelas java yang Anda definisikan sebagai "pendamping" nanti.
drexin
16

Apakah saat kami mencoba untuk membuat instance objek java saja?

Tidak semuanya. Ada dua kasus umum saat Anda mengabaikan newdalam skala. Dengan objek tunggal (yang sering digunakan untuk menyimpan fungsi statis dan sebagai pabrik yang mirip dengan yang Anda lihat di java):

scala> object LonelyGuy { def mood = "sad" }
defined module LonelyGuy

scala> LonelyGuy
res0: LonelyGuy.type = LonelyGuy$@3449a8

scala> LonelyGuy.mood
res4: java.lang.String = sad

Dengan case kelas (sebenarnya, di bawahnya ada class + object = pola pendamping , misalnya memiliki class dan object dengan nama yang sama):

scala> case class Foo(bar: String) 
defined class Foo


scala> Foo("baz")
res2: Foo = Foo(baz)

Jadi ketika Anda bekerja dengan kelas sederhana, aturannya sama dengan Java.

scala> class Foo(val bar: String) 
defined class Foo

scala> new Foo("baz")
res0: Foo = Foo@2ad6a0

// will be a error 
scala> Foo("baz")
<console>:8: error: not found: value Foo
       Foo("baz")

Bonusnya, ada kelas anonim dalam scala, yang dapat dibuat seperti ini:

scala> new { val bar = "baz" }
res2: java.lang.Object{val bar: java.lang.String} = $anon$1@10ee5b8

scala> res2.bar
res3: java.lang.String = baz
om-nom-nom
sumber
1
Anda baik-baik saja di sana kawan?
Jacob B
0

Apakah ketika kita mencoba untuk membuat contoh objek Java saja?

Dengan Scala 3 (yang akan dirilis pertengahan 2020, delapan tahun kemudian), berdasarkan Dotty : never.

Scala 3 akan " new" turun , seperti di utas ini

Aplikasi pembuat memungkinkan untuk menggunakan sintaks panggilan fungsi sederhana untuk membuat instance kelas, bahkan jika tidak ada metode terapan yang diterapkan.

Contoh:

class StringBuilder(s: String) {
   def this() = this(s)
}

StringBuilder("abc")  // same as new StringBuilder("abc")
StringBuilder()       // same as new StringBuilder()

Aplikasi pembuat menggeneralisasi fungsionalitas yang disediakan sejauh ini hanya untuk kelas kasus, tetapi mekanisme bagaimana hal ini dicapai sedikit berbeda.
Alih-alih metode penerapan yang dibuat secara otomatis, kami menambahkan kemungkinan interpretasi baru ke pemanggilan fungsi f(args).

VonC
sumber