Właśnie obejrzałem tę rozmowę Daniela Spiewaka, w której mówi on o zaletach pisania strukturalnego w porównaniu do nominalnego pisania Scali i Java . Przykładem tej różnicy może być następujący kod Java
public interface Foo {
public int length();
}
public interface Bar {
public int length();
}
Foo f = ...;
Bar b = f;
które oczywiście nie skompilowałyby się, ponieważ zgodność typu pomiędzy Foo
iBar
jest określana przez nazwę.
Z drugiej strony system typów strukturalnych może zadeklarować, że oba typy są równe lub kompatybilne, a zatem między innymi umożliwiać sprawdzanie typowania kaczek.
Teraz myślę, że rozumiem większość zalet systemu typów strukturalnych, ale zastanawiam się, czy nie unieważniłoby to bezpieczeństwa typu z przykładów takich jak poniżej
class Foo {
class Bar { /* ... */ }
def takeBar(b: Bar) = { /* ... */ }
def getBar: Bar = new Bar
}
val foo1 = new Foo
val foo2 = new Foo
foo1.takeBar(foo1.getBar) // should compile
foo1.takeBar(foo2.getBar) // should not compile
Czy dobrze rozumiem, że w systemie typu strukturalnego kompiluje się również ostatnia linia, a jeśli tak, to czy nie byłoby to niekorzystne z punktu widzenia bezpieczeństwa typu?
źródło
Odpowiedzi:
W rzeczywistości typy zależne od ścieżki są prostopadłe do strukturalnego vs. nominalne. Nie jest do końca jasne, co oznacza klasa wewnętrzna w kontekście prostego języka o typie strukturalnym. Jest jednak bardzo możliwe do zdefiniowania to . Jeśli miałbyś zdefiniować klasy wewnętrzne w kontekście strukturalnie typowanym, musisz upewnić się, że przypadki takie jak ta, którą wymieniłeś, zostaną odrzucone (z dokładnie tych samych powodów, dla których Scala je odrzuca).
Odrzuciłbyś takie przypadki, robiąc to samo, co robi Scala: zamodeluj typ zależny od ścieżki jako typ egzystencjalny. Ta sama procedura pakowania / rozpakowywania otaczająca dostęp do obiektów byłaby wstrzymana, a wyniki wyglądałyby prawie identycznie jak robi Scala. Wyniki mogą wydawać się nominalną równością typów, ale nadal byłby to strukturalny system typów, ponieważ kwestia zgodności typów będzie nadal rozstrzygana raczej na podstawie interfejsu niż nazwy.
Typowanie strukturalne ma wiele implikacji, ale (być może zaskakujące) większość tych samych pojęć, które wszyscy znamy i uwielbiamy z systemów typu nominalnego, przechodzi w strukturę. Pisanie strukturalne jest niczym innym jak innym sposobem definiowania zgodności typów.
źródło
Wpisywanie strukturalne ułatwia pisanie ogólnego kodu bibliotecznego. Głównym powodem, dla którego ekosystem Java jest tak rozdęty, jest to, że trudno jest łatwo pisać małe biblioteki. Gdyby Java była strukturalnie wpisana, myślę, że byłaby to inna historia i znacznie lepsza sytuacja.
Jedyną wadą, jaką mogę wymyślić przy typowaniu strukturalnym, jest możliwość wolniejszej kompilacji. Nie jestem pewien, czy języki strukturalne generalnie kompilują się wolniej niż te nominalne, czy nie, ale na przykład Golang jest strukturalnie pisany i bardzo szybki w kompilacji.
źródło