5

Zastanawiam się, czy ogólnie możliwe jest ujednolicenie pojęć dziedziczenia i polimorfizmu parametrycznego ("generics"), szczególnie w odniesieniu do wariancji, ale także pod względem tego, w jaki sposób ("składnia") i gdzie (use-site/declaration-site) będą muszą być zdefiniowane?Czy można ujednolicić pojęcia dziedziczenia i polimorfizmu parametrycznego?

Rozważmy ten punkt widzenia:

  • Sub-wpisując e. sol. S <: T może być postrzegane jako zachowanie współzmienne, ponieważ argumenty wejściowe akceptujące T będą również akceptować S.
  • Zmiana "wariancji modelu dziedziczenia" na niezmiennik jest możliwa tylko po stronie definicji przez uniemożliwienie podtypowania (np. Dodanie modyfikatora final do definicji klasy), przeciwstawienie nie jest możliwe, o ile widziałem w większości przypadków
  • polimorfizm parametryczny jest niezmienna domyślnie, ale można CO-/przeciwwskazane wariant

wydaje się być non-znikome pojęcie niedopasowanie pomiędzy obu, zważywszy

  • z języki bólu wygenerowały się przez dopuszczenie "niebezpiecznej" kowariancji (np. sol. String[] <: Object[] w Java/C#)
  • różnic w sposobie polimorfizm dziedziczenie/parametryczna jest uznany i używany w porównaniu do spadków

w niektórych językach można zauważyć, że zarówno praca razem ładnie chociaż, jak

class Foo extends Ordered[Foo] 

do realizacji zamówień/zachowania porównawczego.

  • Czy można sobie wyobrazić, że pojęcia dziedziczenia i polimorfizmu parametrycznej mogą być ujednolicone i zyskać tym samym zachowanie domyślne wariancji (np kowariancji domyślnie czy miałoby to spowodować konieczność oznaczania większości typów z dopiskiem niezmienności zamiast, dlatego właśnie przenoszenie brzydoty do innego punktu)? Czy byłoby to bardziej praktyczne, gdyby struktury danych stały się domyślnie niezmienne?
  • Czy istnieje formalny system, w którym udowodniono, że jest on dobry?
  • Jakie opcje/zmiany składni byłyby najprawdopodobniej konieczne, niezależnie od konkretnego języka programowania?
  • Czy jest jakiś działający przykład lub język, w którym to/coś podobnego już działa?

Odpowiedz

4

Przez kowariancję/warwariancję zwykle oznacza się to. Załóżmy, że X, Y, Z są typy. Załóżmy ponadto, że a → b oznacza typ funkcji z argumentem typu a i wynikiem typu b. <: oznacza relację podtypu, lub może inne pojęcie "zgodności". Strzałka ⇒ wskazuje "pociąga za sobą". Następnie dodaje się trzyma:

X <: Y ⇒ (Z → X) <: (Z → Y) 
X <: Y ⇒ (Y → Z) <: (X → Z) 

Oznacza to, że konstruktor typu funkcja jest kowariantna względem rodzaju wynik (źródła danych) i kontrawariantny względem rodzaju argument (dane umywalka).Jest to podstawowy fakt, a ty mniej więcej nie możesz zrobić niczego zbyt twórczego, jak odwrócenie kierunków strzał. Oczywiście zawsze możesz użyć nie-wariancji zamiast ko- lub kontrawariancji (większość języków tak robi).

Typy obiektów mogą być kodowane kanonicznie za pomocą typów funkcji, więc tutaj również nie ma zbyt wiele swobody. Każdy parametr typu reprezentuje źródło danych (kowariancję) lub pochłaniacz danych (przeciwwskazanie) lub oba (novariant). Jeśli dźwięk jest kontrawariantny w jednym języku, to w innym języku będzie albo sprzeczny, albo niesłuszny.

Myślę, że Scala jest bardzo blisko idealnego języka pod tym względem. Przytaczasz przykład, który przypomina Scalę, więc najprawdopodobniej znasz ten język. Zastanawiam się, dlaczego uważasz, że jego system typów działa dobrze tylko w niektórych przypadkach. Jakie są inne instancje?

Jedna z teoretycznych prac, którą każdy początkujący projektant języka powinien przeczytać, to "Teoria obiektów" Luca Cardelli.

+0

Dzięki za wskazówkę do książki, nie znałem jeszcze tej książki! Zasadniczo zastanawiam się, czy dziedziczenie i PP mają te same podstawy, z różnymi domyślnymi, dostosowanymi i zoptymalizowanymi dla ich postrzeganych przypadków użycia. – soc

+0

"Ładnie w niektórych przypadkach" nie miało być wyłączne. Po prostu uznałem przykład za dobry i prosty przykład, jak te dwie koncepcje mogą ładnie współdziałać ze sobą. Zmieniłem trochę brzmienie. Bardzo lubię Scalę, ale chciałbym mieć kilka poprawnych dziur w prawdziwym kompilatorze, które mają być naprawione, ale brakuje im geniuszu koniecznego do zrobienia tego samemu. :-) – soc

Powiązane problemy