2012-03-15 34 views
70

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 đối tượng trong Scala? Có phải khi chúng tôi cố gắng để khởi tạo các đối tượng Java không?Từ khóa "mới" trong Scala

Trả lời

112

Sử dụng các từ khóa new khi bạn muốn đề cập đến một class 's constructor riêng:

class Foo { } 

val f = new Foo 

Bỏ qua new nếu bạn đang đề cập đến phương pháp đối tượng bạn đồng hành của apply:

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

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

Nếu bạn đã thực hiện một trường hợp lớp học:

case class Foo() 

Scala bí mật tạo ra một đối tượng đồng hành cho bạn, biến nó thành 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 mà nói rằng người bạn đồng hành apply phương thức phải là proxy cho hàm tạo:

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

// These do different things 
> println(new Foo) 
[email protected] 
> println(Foo()) 
7 

Và, vì bạn đã đề cập đến các lớp Java: có - Các lớp Java hiếm khi hav e đối tượng đồng hành với phương thức apply, vì vậy bạn phải sử dụng new và phương thức khởi tạo của lớp thực tế là .

+0

hạng A Java không bao giờ có thể có một đối tượng đồng. Nó có thể có một đối tượng có thể hoạt động như một Nhà máy cho lớp Java - nhưng đối tượng này không phải là đối tượng đồng hành của nó. – sschaef

+0

@Antoras Kể từ khi các lớp Scala biên dịch sang Java bytecode, và có thể được phân phối dưới dạng biên dịch, Scala có thể cho biết sự khác biệt giữa đồng hành Scala thực và lớp Foo $ với thành phần MODULE $ tĩnh không? – Owen

+1

Tôi nghĩ rằng scalac có thể khác nhau bởi vì nó là spec'ed rằng một đối tượng đồng hành phải được khai báo trong cùng một tập tin như lớp đồng hành của nó.Bởi vì "thuộc tính" đồng hành chỉ tồn tại trong Scala và không phải trên cấp độ bằng giọng nói của Bytecode, phải kiểm tra mã Scala và không phải mã Bytecode để chắc chắn rằng thông số được theo sau. – sschaef

13

Có phải khi chúng tôi cố gắng khởi tạo các đối tượng java không?

Không hề. Có hai trường hợp chung khi bạn ommit new trong scala. Với đối tượng singleton (được oftenly sử dụng để lưu trữ các chức năng tĩnh và như một loại 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 = [email protected] 

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

Với case classes (trên thực tế, bên dưới có lớp + object = companion mẫu, 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 học đơn giản, 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 = [email protected] 

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

thưởng, có một lớp học vô 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} = [email protected] 

scala> res2.bar 
res3: java.lang.String = baz 
Các vấn đề liên quan