Na poziomie abstrakcyjnym możesz uwzględnić dowolne elementy w projektowanym języku.
Na poziomie implementacji nieuniknione jest, że niektóre z tych rzeczy będą łatwiejsze do wdrożenia, niektóre będą skomplikowane, niektóre mogą być wykonane szybko, inne będą działać wolniej i tak dalej. Aby to wyjaśnić, projektanci często muszą podejmować trudne decyzje i kompromisy.
Na poziomie implementacji jednym z najszybszych sposobów uzyskania dostępu do zmiennej jest znalezienie jej adresu i załadowanie zawartości tego adresu. W większości procesorów znajdują się szczegółowe instrukcje dotyczące ładowania danych z adresów i instrukcje te zwykle muszą wiedzieć, ile bajtów muszą załadować (jeden, dwa, cztery, osiem itd.) I gdzie umieścić dane, które ładują (pojedynczy rejestr, rejestr para, rejestr rozszerzony, inna pamięć itp.). Znając rozmiar zmiennej, kompilator może dokładnie wiedzieć, które instrukcje należy wydać dla zastosowań tej zmiennej. Nie znając wielkości zmiennej, kompilator musiałby zastosować coś bardziej skomplikowanego i prawdopodobnie wolniejszego.
Na poziomie abstrakcyjnym punktem podtypu jest możliwość użycia instancji jednego typu, w których oczekuje się równego lub bardziej ogólnego typu. Innymi słowy, można napisać kod, który oczekuje obiektu określonego typu lub czegokolwiek bardziej pochodnego, nie wiedząc z wyprzedzeniem, co to dokładnie będzie. I oczywiście, ponieważ więcej typów pochodnych może dodawać więcej elementów danych, typ pochodny niekoniecznie musi mieć takie same wymagania dotyczące pamięci jak typy podstawowe.
Na poziomie implementacji nie ma prostego sposobu, aby zmienna o z góry określonym rozmiarze zawierała instancję o nieznanym rozmiarze i była dostępna w sposób, który normalnie nazwiemy wydajnym. Istnieje jednak sposób, aby trochę przesunąć rzeczy i użyć zmiennej nie do przechowywania obiektu, ale do zidentyfikowania obiektu i umożliwienia przechowywania go w innym miejscu. W ten sposób jest odniesienie (np. Adres pamięci) - dodatkowy poziom pośredni, który zapewnia, że zmienna musi przechowywać tylko pewien rodzaj informacji o stałym rozmiarze, o ile możemy znaleźć obiekt na podstawie tych informacji. Aby to osiągnąć, wystarczy załadować adres (stały rozmiar), a następnie możemy pracować jak zwykle, używając przesunięć obiektu, o których wiemy, że są poprawne, nawet jeśli obiekt ten zawiera więcej danych w przesunięciach, których nie znamy. Możemy to zrobić, ponieważ nie
Na poziomie abstrakcyjnym ta metoda pozwala przechowywać (odwołanie do a) string
w object
zmiennej bez utraty informacji, które ją tworzą string
. Wszystkie typy mogą dobrze działać w ten sposób i można powiedzieć, że pod wieloma względami jest elegancki.
Jednak na poziomie implementacji dodatkowy poziom pośredni wymaga większej liczby instrukcji i na większości architektur powoduje, że każdy dostęp do obiektu jest nieco wolniejszy. Możesz zezwolić kompilatorowi na wyciśnięcie większej wydajności z programu, jeśli dołączysz w swoim języku niektóre często używane typy, które nie mają takiego dodatkowego poziomu pośredniego (odniesienie). Jednak po usunięciu tego poziomu pośrednictwa kompilator nie może już pozwolić na podtyp w bezpieczny sposób dla pamięci. Dzieje się tak, ponieważ jeśli dodasz więcej elementów danych do swojego typu i przypiszesz do bardziej ogólnego typu, wszelkie dodatkowe elementy danych, które nie mieszczą się w przestrzeni przydzielonej dla zmiennej docelowej, zostaną usunięte.