Làm thế nào là Không có kiểu con của mọi loại khác trong Scala


19

Tôi đang tham gia khóa học coursera của Martin Oderky về lập trình chức năng với scala, và bây giờ tôi đã học được hai điều mà cùng nhau không có ý nghĩa:

  1. Scala không hỗ trợ nhiều kế thừa
  2. Nothing là một kiểu con của mọi loại khác

Hai tuyên bố này không thể sống cùng nhau, vậy chính xác thì điều này được thực hiện như thế nào? và chính xác ý nghĩa của "kiểu con của mọi loại khác"

Chỉnh sửa 1

Trong API Scala , Nothingđược định nghĩa là abstract final class Nothing extends Any... vậy làm thế nào để mở rộng các lớp khác?


Trang này có thể giúp một chút: artima.com/pin1ed/scalas-hierarchy.html
jhewlett

Theo như tôi có thể thấy nó được định nghĩa là "đặc điểm cuối cùng Không có gì kéo dài bất kỳ" scala-lang.org/api/2.7.6/scala/Noth.html
Den

8
Bạn đang nhầm lẫn các loại và các lớp. Hai cái đó là những thứ rất khác nhau. Thật không may, bạn không phải là người duy nhất bị nhầm lẫn bởi sự khác biệt đó và thực sự không may, một số người bị nhầm lẫn là nhà thiết kế của các ngôn ngữ phổ biến như Java, C # và C ++. Nó không nói rằng đó Nothinglà một lớp con của mọi lớp khác. Nó nói rằng nó là một kiểu con của mọi loại khác .
Jörg W Mittag

1
@delnan: Các giao diện của Java được lấy trực tiếp từ các giao thức của Smalltalk. Trong Smalltalk, chỉ có các giao thức là loại, lớp không có. Trong Java, cả giao diện lớp là các loại. Sai rồi. Các lớp không có loại, chỉ có giao diện. Thực tế là tất cả các ngôn ngữ này có những thứ thuộc loại và không phải là các lớp là không liên quan. Vấn đề là trong các ngôn ngữ đó các lớp là loại, đó là sai.
Jörg W Mittag

1
@ JörgWMittag Đó là một tuyên bố khác và cực kỳ gây tranh cãi (tôi có xu hướng đồng ý rằng nó có hại, nhưng tôi sẽ không gán cho điều này là hiểu nhầm về việc gõ). Không có điểm trong thảo luận về nó ở đây.

Câu trả lời:


27

Subtyping và thừa kế là hai điều khác nhau! Nothingkhông mở rộng tất cả mọi thứ, nó là một kiểu con , nó chỉ mở rộng Any.

Thông số kỹ thuật [§3.5.2] có trường hợp đặc biệt chi phối mối quan hệ phụ của Nothing:

§3.5.2 Sự phù hợp

  • [...]
  • Đối với mọi loại giá trị
    T,scala.Nothing <: T <:scala.Any
  • Đối với mỗi hàm tạo kiểu T(với bất kỳ số lượng tham số loại nào)
    scala.Nothing <: T <: scala.Any
  • [...]

Trong trường hợp <:cơ bản có nghĩa là "là một subtype của".

Về cách thức thực hiện: Chúng tôi không biết, đó là phép thuật của trình biên dịch và một chi tiết triển khai.

Thông thường, một ngôn ngữ sẽ làm những việc mà bạn là một lập trình viên không thể làm được. Là một đối trọng với Nothing: Mọi thứ trong Scala được thừa hưởng từ Any, mọi thứ ngoại trừ Any . Tại sao không Anyđược thừa hưởng từ một cái gì đó? Bạn không thể làm điều đó. Tại sao Scala có thể làm điều đó? Vâng, bởi vì Scala đặt ra các quy tắc, không phải bạn. Nothinglà một kiểu con của mọi thứ chỉ là một ví dụ khác của điều này.


10
BTW: điều này hoàn toàn giống với nullviệc được gán cho một trường thuộc mọi loại trong Java. Tại sao điều đó có thể? Là nullmột ví dụ của mỗi lớp? Không, có thể bởi vì trình biên dịch nói như vậy. Giai đoạn.
Jörg W Mittag

8
Nếu tôi có thể nâng cao điều này hàng trăm lần, tôi sẽ làm thế. Các kiểulớp khó hiểu là một trong những điều tồi tệ nhất mà ngôn ngữ Java mang lại cho chúng ta.
Jörg W Mittag

1
Đối với những tâm hồn tò mò về sự khác biệt giữa thừa kế và các kiểu con cmi.ac.in/~madhavan/cifts/pl2006/lecturenotes/lecture-notes/, tuy nhiên tôi không mua nó - nếu bạn thừa kế (như extendstrong Java, và không phải là sáng tác ) bạn làm điều đó cho subtyping sau khi tất cả.
greenoldman

11

Khi anh ta nói rằng Scala không hỗ trợ nhiều kế thừa, thì anh ta đề cập đến việc kế thừa một phương thức thực hiện nhiều lần. Tất nhiên, bạn có thể triển khai nhiều giao diện / đặc điểm trong một lớp và chúng thậm chí có thể định nghĩa cùng một phương thức, nhưng bạn không bị xung đột giữa các triển khai khác nhau do tuyến tính hóa.

Nói chung, nếu bạn có một lớp C1với một phương thức f()và một lớp C2cũng với một phương thức f(), thì nhiều kế thừa có nghĩa là bạn có thể bằng cách nào đó kế thừa cả hai triển khai f(). Điều này có thể dẫn đến nhiều vấn đề khác nhau, mà Scala giải quyết bằng cách chỉ cho phép bạn thừa hưởng từ một lớp duy nhất và trong trường hợp có nhiều đặc điểm bằng cách chọn một triển khai dựa trên thứ tự các đặc điểm.

Đối với Nothingmọi thứ thực sự đơn giản, bởi vì không có gì không có thuộc tính hoặc phương thức được xác định. Vì vậy, bạn không thể có bất kỳ xung đột thừa kế. Nhưng tôi cho rằng hầu hết sự ngạc nhiên của bạn đến từ một sự hiểu biết khác nhau về đa thừa kế.

Một khi bạn hiểu rằng tuyến tính hóa đặc điểm loại bỏ một cách hiệu quả bất kỳ sự mơ hồ nào của thừa kế và chúng tôi không đề cập đến việc thừa kế từ nhiều tính trạng như nhiều di truyền do đó, thì bạn sẽ ổn thôi.

Về việc này được nhận ra như thế nào: trình biên dịch cuối cùng chịu trách nhiệm cho việc này. Xem phần tuân thủ phần đặc tả ngôn ngữ Scala 3.5.2, trong số các thuộc tính khác bao gồm:

For every type constructor T (with any number of type parameters), scala.Nothing <: T <: scala.Any.

Hay nói cách khác, nếu bạn muốn triển khai một trình biên dịch chính xác, nó phải xử lý Nothingnhư một kiểu con của mọi thứ theo đặc tả. Vì các lý do rõ ràng, Nothingkhông được xác định để mở rộng từ tất cả các lớp được tải vào hệ thống, nhưng mức độ liên quan của việc xác định Nothinglà kiểu con được giới hạn ở tất cả các nơi, trong đó phân nhóm có liên quan.

Một điểm quan trọng ở đây là không tồn tại trường hợp loại Nothing, do đó, việc xử lý của nó bị giới hạn nghiêm ngặt đối với việc kiểm tra kiểu, tất cả nằm trong địa hạt của trình biên dịch.


2
Điều tôi vẫn không hiểu là làm thế nào được thực hiện ... Xem phần chỉnh sửa cho câu hỏi của tôi
vainolo

1
"sự liên quan của việc định nghĩa Không có gì là phân nhóm được giới hạn ở tất cả các nơi, trong đó phân nhóm có liên quan." Bạn muốn truyền đạt điều gì? X có liên quan trong đó X có liên quan?
phant0m
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.