Biorę kurs Martina Oderskiego na programowanie funkcjonalne ze Scalą i na razie nauczyłem się dwóch rzeczy, które razem nie mają sensu:
- Scala nie obsługuje wielokrotnego dziedziczenia
Nothing
jest podtypem każdego innego typu
Te dwa stwierdzenia nie mogą żyć razem, więc jak dokładnie to się robi? i co dokładnie oznacza „podtyp każdego innego typu”
Edytuj 1
W API Scala , Nothing
jest zdefiniowany jako abstract final class Nothing extends Any
... więc jak można go przedłużyć innych klas?
programming-languages
scala
vainolo
źródło
źródło
Nothing
jest to podklasa każdej innej klasy. Mówi, że jest to podtyp każdego innego typu .Odpowiedzi:
Składanie i dziedziczenie to dwie różne rzeczy!
Nothing
nie rozszerza wszystkiego, jest podtypem , rozszerza sięAny
.Opis [§3.5.2] ma szczególny przypadek zarządzającego podtypy-związek
Nothing
:Gdzie w
<:
zasadzie oznacza „jest podtypem”.Jak to się dzieje: nie wiemy, to magia kompilatora i szczegóły implementacji.
Dość często język robi rzeczy, których nie potrafisz jako programista. Jako odpowiednik
Nothing
: Wszystko w Scali dziedziczyAny
, wszystko opróczAny
. DlaczegoAny
czegoś nie dziedziczy? Nie możesz tego zrobić. Dlaczego Scala może to zrobić? Cóż, ponieważ Scala ustalił zasady, nie ty.Nothing
bycie podtypem wszystkiego jest po prostu innym tego przykładem.źródło
null
przypisanie do pola każdego typu w Javie. Dlaczego to jest możliwe? Czynull
jest instancją każdej klasy? Nie, jest to możliwe, ponieważ kompilator tak mówi. Kropka.extends
w Javie, a nie jako komponuj) ) w końcu robisz to dla podtypu.Kiedy mówi, że Scala nie obsługuje wielokrotnego dziedziczenia, wówczas odnosi się do dziedziczenia implementacji metody wiele razy. Oczywiście można zaimplementować wiele interfejsów / cech w klasie, a nawet zdefiniować tę samą metodę, ale nie występuje konflikt między różnymi implementacjami z powodu linearyzacji cechy.
Ogólnie, jeśli masz klasę
C1
z metodąf()
i klasęC2
również z metodąf()
, to wielokrotne dziedziczenie oznacza, że możesz w jakiś sposób odziedziczyć obie implementacjef()
. Może to prowadzić do różnych problemów, które Scala rozwiązuje, pozwalając ci odziedziczyć po jednej klasie, aw przypadku wielu cech, wybierając jedną implementację na podstawie kolejności cech.Co do
Nothing
rzeczy, są naprawdę proste, ponieważ nic nie ma zdefiniowanych atrybutów ani metod. Więc nie możesz mieć żadnych konfliktów spadkowych. Ale zakładam, że większość twoich niespodzianek wynika z innego zrozumienia wielokrotnego dziedziczenia.Kiedy zrozumiesz, że linearyzacja cech skutecznie eliminuje jakąkolwiek dwuznaczność dziedziczenia, i że nie mówimy o dziedziczeniu z wielu cech jako wielokrotnego dziedziczenia z tego powodu, powinieneś być w porządku.
Jak to się dzieje: kompilator jest ostatecznie za to odpowiedzialny. Zobacz specyfikację języka Scala w rozdziale 3.5.2, która obejmuje między innymi:
Innymi słowy, jeśli chcesz poprawnie wdrożyć kompilator, musi on obsługiwać
Nothing
jako podtyp wszystkiego według specyfikacji. Z oczywistych powodówNothing
nie zdefiniowano, aby obejmowało wszystkie klasy załadowane do systemu, ale istotność zdefiniowaniaNothing
jako podtyp jest ograniczona do wszystkich miejsc, w których istotne jest podtypowanie.Ważną kwestią jest tutaj to, że nie istnieje żadna instancja typu
Nothing
, dlatego jej leczenie jest ściśle ograniczone do sprawdzania typu, co leży w sferze kompilatora.źródło