W systemie z dynamicznym typowaniem wartości mają typy w czasie wykonywania, ale zmienne i funkcje nie. W systemie o typie statycznym zmienne i funkcje mają typy znane i sprawdzane podczas kompilacji. Np. W Pythonie x
może być wszystko ; w czasie wykonywania, jeśli jest 1
to liczba, a jeśli tak "foo"
, to ciąg. Będziesz wiedział tylko, który typ x
był w czasie wykonywania, i może być inny przy każdym uruchomieniu programu. W języku takim jak Java piszesz, int x
jeśli x
ma być liczbą, i wiesz, że w czasie kompilacji x
zawsze musi to być int
.
Oba typy „jawne” i „niejawne” odnoszą się do systemów typu statycznego . Cechą charakterystyczną systemu statycznego jest to, że typy są znane w czasie kompilacji, ale niekoniecznie muszą być zapisane. W Javie typy są jawne - musisz je zapisać. W Javie metoda może wyglądać mniej więcej tak:
public int foo(String bar, Object baz) { ... }
Typy są znane zarówno w czasie kompilacji (statyczne), jak i zapisywane (jawne). Istnieją jednak języki, które nie zmuszają Cię do napisania tego typu. Mogą wywnioskować rodzaj funkcji na podstawie jej ciała i sposobu jej użycia. Przykładem może być OCaml, w którym możesz napisać coś takiego:
let foo x = x + 1
Odkąd +
używałeś, OCaml może zorientować się, że x
to int
wszystko musi być samo w sobie. Tak więc typ foo
( foo : int -> int
) jest znany w czasie kompilacji, podobnie jak przykład Java. Jest całkowicie statyczny. Ponieważ jednak kompilator może samodzielnie ustalić, jakie typy muszą być, nie musisz sam ich zapisywać: są niejawne.
W skrócie: to, czy system typów jest jawny czy niejawny, jest własnością systemów statycznych . Jest to zupełnie inne pytanie, czy system typów jest dynamiczny czy statyczny.
Często masz systemy typów, które są czasami jawne, a czasem niejawne.
Na przykład uważam, że C # pozwala wnioskować typy za pomocą var
słowa kluczowego. Zamiast pisać int x = 10
, możesz pisać, var x = 10
a kompilator odkrywa, że to x
musi być int
. C ++ robi coś podobnego z auto
. Systemy te są zwykle jawne, ale mają pewne wnioski.
Z drugiej strony istnieją systemy, które są zwykle niejawne, ale czasami zmuszają cię do napisania podpisu typu. Haskell jest świetnym przykładem. Przez większość czasu Haskell może wnioskować o typach dla Ciebie. Czasami jednak możesz napisać dwuznaczny kod show . read
, w którym Haskell nie jest w stanie samodzielnie rozróżnić typów. W tym przypadku można byłoby zmuszone do jednoznacznie określić typ albo show
albo read
. Ponadto niektóre bardziej zaawansowane funkcje systemu typów (takie jak polimorfizm rangi n) powodują, że wnioskowanie jest nierozstrzygalne - to znaczy nie ma gwarancji, że się zatrzyma. Oznacza to, że kod korzystający z tej funkcji często wymaga wyraźnych podpisów typu.
statyczny vs dynamiczny opisuje, kiedy typy są sprawdzane (mniej więcej w czasie kompilacji lub w czasie wykonywania)
Nominalny vs strukturalny opisuje, kiedy dwa typy są uważane za takie same.
(I są odmiany, najbardziej znanym jest wariant typowania strukturalnego, który uwzględnia tylko to, co jest używane zamiast całego typu znanego jako typowanie kacze).
Cztery kombinacje (statyczny nominalny, statyczny strukturalny, dynamiczny nominalny, dynamiczny strukturalny) są możliwe, a języki dość często nie są wyłącznie w jednej klasie, ale mają aspekty, które są w innych.
Na przykład systemy typów w C ++ są statyczne, głównie nominalne, ale strukturalne, jeśli wziąć pod uwagę szablony (a część problemów związanych z koncepcjami w C ++ można rozważyć jako konflikt między tymi, którzy chcą od pisania typu „duck” do pełnej formy pisania strukturalnego i tych, którzy chcą przejść do pisania nominalnego). A użycie klas i dziedziczenia pozwala w niektórych przypadkach używać dynamicznego i nominalnego pisania.
Język, w którym systemy typu dynamicznego często używają typowania strukturalnego, ale CLOS jako aspekty nominalne.
źródło
Zazwyczaj tak nie jest. Wpisywanie strukturalne oznacza, że
B
jest to podtyp tego,A
czy może on spełniaćA
interfejs. Zazwyczaj oznacza to posiadanie członków o tej samej nazwie; nie tylko ta sama struktura w pamięci.Różni się to od typowania nominalnego, które wymaga nadpisania w deklaracji.
źródło
Najlepsze wyjaśnienie, jakie widziałem na temat rozróżnienia pomiędzy (a właściwie subskrybowaniem) systemów typu dynamicznego i statycznego, znajduje się w tym blogu autorstwa Boba Harpera:
Jego główny punkt można podsumować jako:
źródło