2015-07-21 16 views
8

tôi thấy một số mã từ thư viện:Tại sao lớp scala cần phải mở rộng một cách rõ ràng AnyRef

trait A extends scala.AnyRef 
trait B extends scala.AnyRef with A 

Tại sao A cần phải mở rộng một cách rõ ràng AnyRef? Không phải tất cả các lớp đều bắt nguồn từ AnyRef chưa?

Tại sao B cần mở rộng AnyRef mặc dù A đã thực hiện việc này chưa? Sự khác biệt để thay đổi mã trên là gì:

trait A 
trait B extends A 
+2

Thư viện là gì? –

+0

một thư viện nổi tiếng. không muốn nhắc đến tên ở đây. – jiangok

+4

Tại sao không? Một số bối cảnh có thể giúp tìm ra nếu có bất kỳ lý do này. –

Trả lời

7

Tôi không nói gì khác biệt.

Từ scala documentation

lớp người dùng định nghĩa xác định các loại tài liệu tham khảo theo mặc định; tức là họ luôn luôn (gián tiếp) phân lớp scala.AnyRef.

Tiếp tục chứng minh điểm

scala> trait A 
defined trait A 

scala> trait B extends A 
defined trait B 

scala> val a = new A { } 
a: A = [email protected] 

scala> val b = new B { } 
b: B = [email protected] 

scala> a.isInstanceOf[AnyRef] 
res4: Boolean = true 

scala> b.isInstanceOf[AnyRef] 
res7: Boolean = true 
2

Bạn không cần phải mở rộng một cách rõ ràng AnyRef. AnyRef tương đương với đối tượng của Java trong Scala. Bằng cách tạo một thể hiện của một lớp, cá thể đó sẽ mở rộng AnyRef ngầm bất kể nếu nó được đề cập rõ ràng trong một trong các lớp siêu của nó hay không.

Các mã sau chỉ tạo ra một lớp vô danh, do đó nó cũng mở rộng AnyRef ngầm:

trait A 
val a = new A { } 

Dưới đây là lời giải thích từ scala-lang.org:

Các lớp cha của tất cả lớp scala.Any có hai lớp con trực tiếp scala.AnyVal và scala.AnyRef đại diện cho hai thế giới lớp khác nhau: các lớp giá trị và các lớp tham chiếu. Tất cả các lớp giá trị được xác định trước; chúng tương ứng với các kiểu nguyên thủy của các ngôn ngữ giống như Java. Tất cả các lớp khác định nghĩa các kiểu tham chiếu. Các lớp do người dùng định nghĩa xác định loại tham chiếu theo mặc định; tức là họ luôn (gián tiếp) scala.AnyRef phân lớp. Mỗi lớp do người dùng định nghĩa trong Scala ngầm mở rộng đặc điểm scala.ScalaObject. Các lớp từ cơ sở hạ tầng mà Scala đang chạy (ví dụ: môi trường thời gian chạy Java) không mở rộng scala.ScalaObject. Nếu Scala được sử dụng trong ngữ cảnh của môi trường chạy Java, thì scala.AnyRef tương ứng với java.lang.Object. Xin lưu ý rằng biểu đồ ở trên cũng cho thấy chuyển đổi tiềm ẩn được gọi là chế độ xem giữa các lớp giá trị. Dưới đây là một ví dụ chứng minh rằng cả hai con số, ký tự, các giá trị boolean, và chức năng là những vật thể giống như mọi đối tượng khác:

http://docs.scala-lang.org/tutorials/tour/unified-types.html

Kể từ Scala 2.10 bạn cũng có thể mở rộng AnyVal. Từ scala-lang.org:

AnyVal là lớp gốc của tất cả các loại giá trị, mô tả các giá trị không được triển khai làm đối tượng trong hệ thống máy chủ cơ bản. Trước Scala 2.10, AnyVal là một đặc điểm kín. Tuy nhiên, bắt đầu với Scala 2.10, có thể định nghĩa một lớp con của AnyVal được gọi là lớp giá trị do người dùng định nghĩa được trình biên dịch xử lý đặc biệt.Các lớp giá trị người dùng được định nghĩa đúng cách cung cấp một cách để cải thiện hiệu năng trên các kiểu do người dùng định nghĩa bằng cách tránh phân bổ đối tượng trong thời gian chạy và bằng cách thay thế các lời gọi phương thức ảo bằng các lời gọi phương thức tĩnh.

+0

Nó có thể là giá trị thêm thông tin về 'AnyVal' được thêm vào sau này, mà làm cho phần" họ luôn luôn ... subclass scala.AnyRef "không chính xác đúng sự thật. – Suma

+0

Bằng cách kiểm tra với isInstanceOf bạn sẽ thấy rằng người dùng tạo ra các lớp mở rộng AnyVal thực sự cũng mở rộng AnyRef. Thật kỳ lạ nhưng đó là cách nó được thực hiện. –

+0

Điều đó không đúng. Nó chỉ xảy ra rằng 'isInstanceOf' hoàn toàn phụ thuộc vào kiểu thời gian chạy jvm, và như những thông tin rò rỉ đó là một chi tiết thực hiện khá nhiều. Khi bạn gọi 'isInstanceOf' trên một thể hiện lớp giá trị nào đó, giá trị đầu tiên được đóng hộp, và tự nhiên, cá thể đóng hộp này mở rộng' Object' (aka 'AnyRef'). Bạn có thể gọi nó là một lỗi, một hành vi đáng ngạc nhiên, hoặc một trường hợp trắng trợn của [trừu tượng bị rò rỉ] (https://en.wikipedia.org/wiki/Leaky_abstraction). Nhưng bạn không thể nói rằng một 'AnyVal' là một' AnyRef'. –

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