2012-09-01 36 views
12

Scala cho phép bạn ghi đè một phương pháp trong 2 cách pháp lý:phương pháp trọng trong Scala

Với siêu lớp:

class A { 
    def a = "A" 
} 

Chúng ta có thể ghi đè lên các phương pháp "a" bằng cách:

class B extends A { 
    override def a = "B" 
} 

class B extends A { 
    override def a() = "B" 
} 

cả hai dường như là quá mức ide phương pháp "a" một cách chính xác. Quyết định thiết kế đằng sau điều này là gì? Tại sao cho phép "a()" trong B ghi đè "a" trong A?

+1

'a()' và 'a' là cả hai phương thức có tên' a' không có đối số nghĩa là có số không bằng 0, nghĩa là chúng giống hệt nhau. Tại sao họ không cho phép điều đó? – oldrinb

Trả lời

14

này không phải lúc nào cũng như vậy (từ nhật ký thay đổi the language specification):

Scala phiên bản 2.0 cũng làm giãn các quy tắc của trọng đối với danh sách tham số có sản phẩm nào với. Định nghĩa sửa đổi của thành viên phù hợp (§5.1.3) làm cho nó bây giờ có thể ghi đè lên một phương thức với một rõ ràng, nhưng sách tham số trống () với một phương pháp parameterless, và phó lại.

Bạn chính xác rằng điều này có vẻ như một quyết định thiết kế kỳ quặc, vì có sự khác biệt quan sát giữa các phương pháp không tham số và phương pháp có danh sách tham số trống. Ví dụ, giả sử bạn có những điều sau đây:

class A { def a = "A" } 
class B extends A { override def a = "B" } 
class C extends A { override def a() = "C" } 

Bây giờ chúng ta có thể viết như sau, như mong đợi:

scala> (new B).a 
res0: java.lang.String = B 

scala> (new C).a 
res1: java.lang.String = C 

Và đây:

scala> (new C).a() 
res2: java.lang.String = C 

Nhưng không này:

scala> (new B).a() 
<console>:10: error: not enough arguments for method apply: (index: Int)Char in class StringOps. 
Unspecified value parameter index. 
       (new B).a() 

Vì vậy, Scala thực hiện một bản phân phối nction giữa hai, mà rõ ràng phải được phản ánh trong bytecode. Giả sử chúng ta biên dịch như sau:

class A { def a = "A" } 
class B extends A { override def a = "B" } 

Và sau đó chạy:

javap -verbose B > noArgList.txt 

Sau đó, thay đổi mã này:

class A { def a = "A" } 
class B extends A { override def a() = "B" } 

biên dịch lại, và chạy:

javap -verbose B > emptyArgList.txt 

Và cuối cùng kiểm tra sự khác biệt:

< MD5 checksum 88aeebf57b645fce2b2fcd2f81acdbbd 
--- 
> MD5 checksum 3733b3e4181b4b2f4993503d4c05770e 
32c32 
< #18 = Utf8    }1A! 
           \t\t!ICaT-9uszaE\r)\"a\tI!!\"1Q!Dg 
jiz\"a\tAQ!BY\t!Y             G.Y11bU2bY|%M[3di\")C%1A(
       /A$H3)!dGYtwMCQM^1\nyI\"AB*ue&tw\r 
--- 
> #18 = Utf8    }1A! 
           \t\t!ICaT-9uszaE\r)\"a\tI!!\"1Q!Dg 
jiz\"a\tAQ!BY\t!             G.Y11bU2bY|%M[3di\")C%1A(
       /A$H3)!dGYtwMCQM^1\nyI\"AB*ue&tw\r 

Vì vậy, có sự khác biệt — hai phiên bản có các giá trị khác nhau cho chú thích ScalaSignature.

Đối với tại sao sự thay đổi đã được thực hiện trong Scala 2.0: đặc tả lưu ý rằng nó cho phép này:

class C { 
    override def toString: String = ... 
} 

đoán của tôi là các nhà thiết kế ngôn ngữ chỉ không thấy một lý do để yêu cầu người dùng hãy nhớ cách tiếp cận các phương pháp ghi đè được sử dụng trong các trường hợp như thế này.

+0

Vì tôi mới bắt đầu học Scala, bạn có thể cho tôi biết chú thích ScalaSignature được sử dụng để làm gì không? – platypus

+0

Đó là một chi tiết triển khai ở mức độ khá thấp mà bạn không cần phải lo lắng trong một thời gian dài, [nếu có] (http://stackoverflow.com/questions/11985096/should-we-use-the-scalasignature- trực tiếp). Vai trò của nó là cho phép trình biên dịch Scala tạo ra sự khác biệt như thế này. –

Các vấn đề liên quan