Tôi có một câu hỏi rất đơn giản - khi nào chúng ta nên áp dụng từ khóa mới khi tạo các đối tượng trong Scala? Có phải khi chúng ta cố gắng khởi tạo các đối tượng Java chỉ?
Câu trả lời:
Sử dụng new
từ khóa khi bạn muốn tham chiếu đến class
phương thức khởi tạo của riêng mình:
class Foo { }
val f = new Foo
Bỏ qua new
nếu bạn đang đề cập đến apply
phương thức của đối tượng đồng hành :
class Foo { }
object Foo {
def apply() = new Foo
}
// Both of these are legal
val f = Foo()
val f2 = new Foo
Nếu bạn đã tạo một lớp trường hợp:
case class Foo()
Scala bí mật tạo một đối tượng đồng hành cho bạn, biến nó thành thế này:
class Foo { }
object Foo {
def apply() = new Foo
}
Vì vậy, bạn có thể làm
f = Foo()
Cuối cùng, hãy nhớ rằng không có quy tắc nào nói rằng apply
phương thức đồng hành phải là một proxy cho hàm tạo:
class Foo { }
object Foo {
def apply() = 7
}
// These do different things
> println(new Foo)
test@5c79cc94
> println(Foo())
7
Và, vì bạn đã đề cập đến các lớp Java: vâng - Các lớp Java hiếm khi có các đối tượng đồng hành với một apply
phương thức, vì vậy bạn phải sử dụng new
và hàm tạo của lớp thực tế.
Có phải khi chúng ta cố gắng khởi tạo các đối tượng java chỉ?
Không có gì. Có hai trường hợp chung khi bạn bỏ qua new
trong scala. Với các đối tượng singleton (thường được sử dụng để lưu trữ các hàm tĩnh và như một loại nhà máy tương tự như những gì bạn có thể thấy trong 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
Với các lớp trường hợp (thực tế, bên dưới có lớp + đối tượng = mẫu đồng hành , ví dụ: có lớp và đối tượng có cùng tên):
scala> case class Foo(bar: String)
defined class Foo
scala> Foo("baz")
res2: Foo = Foo(baz)
Vì vậy, khi bạn làm việc với một lớp đơn giản, các quy tắc cũng giống như với 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")
Phần thưởng, có một lớp ẩn danh trong scala, có thể được xây dựng như thế này:
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
Có phải khi chúng ta cố gắng khởi tạo các đối tượng Java chỉ?
Với Scala 3 (sẽ được phát hành vào giữa năm 2020, tám năm sau), dựa trên Dotty : không bao giờ.
Scala 3 sẽ giảm " new
", như trong chuỗi này
Các ứng dụng của người tạo cho phép sử dụng cú pháp gọi hàm đơn giản để tạo các thể hiện của một lớp, ngay cả khi không có phương thức áp dụng nào được triển khai.
Thí dụ:
class StringBuilder(s: String) {
def this() = this(s)
}
StringBuilder("abc") // same as new StringBuilder("abc")
StringBuilder() // same as new StringBuilder()
Ứng dụng của người tạo khái quát hóa một chức năng được cung cấp cho đến nay chỉ dành cho các lớp trường hợp, nhưng cơ chế đạt được điều này hơi khác một chút.
Thay vì một phương thức áp dụng được tạo tự động, chúng tôi thêm một cách diễn giải khả thi mới cho một lệnh gọi hàmf(args)
.