W rzeczywistości type
słowo kluczowe w Scali może zrobić znacznie więcej niż tylko aliasowanie skomplikowanego typu do krótszej nazwy. Wprowadza członków typu .
Jak wiesz, klasa może mieć członków pól i członków metod. Cóż, Scala pozwala również na to, aby klasa miała członków typu.
W twoim konkretnym przypadku type
jest rzeczywiście wprowadzenie aliasu, który pozwoli ci napisać bardziej zwięzły kod. System typów po prostu zastępuje alias rzeczywistym typem podczas sprawdzania typu.
Ale możesz też mieć coś takiego
trait Base {
type T
def method: T
}
class Implementation extends Base {
type T = Int
def method: T = 42
}
Podobnie jak każdy inny element członkowski klasy, elementy członkowskie typu mogą być również abstrakcyjne (po prostu nie określasz, jaka jest ich wartość) i można je przesłonić w implementacjach.
Składowe typu można postrzegać jako podwójne elementy ogólne, ponieważ wiele rzeczy, które można zaimplementować za pomocą typów ogólnych, można przetłumaczyć na elementy członkowskie typu abstrakcyjnego.
Więc tak, mogą być używane do aliasingu, ale nie ograniczaj ich tylko do tego, ponieważ są one potężną cechą systemu typów Scali.
Zobacz tę doskonałą odpowiedź, aby uzyskać więcej informacji:
Scala: typy abstrakcyjne a typy ogólne
Podobała mi się odpowiedź Rolanda Ewalda, ponieważ opisał ją za pomocą bardzo prostego przypadku użycia aliasu typu, a po więcej szczegółów przedstawił bardzo fajny tutorial. Ponieważ jednak w tym poście wprowadzono inny przypadek użycia nazwany typami składowymi , chciałbym wspomnieć o najbardziej praktycznym przypadku użycia, który bardzo mi się spodobał: (ta część jest wzięta stąd :)
Typ abstrakcyjny:
T powyżej mówi, że ten typ, który będzie używany, jest jeszcze nieznany iw zależności od konkretnej podklasy zostanie zdefiniowany. Najlepszym sposobem zawsze na zrozumienie koncepcji programowania jest podanie przykładu: Załóżmy, że masz następujący scenariusz:
Tutaj otrzymasz błąd kompilacji, ponieważ metoda eat w klasach Cow i Tiger nie przesłania metody eat w klasie Animal, ponieważ ich typy parametrów są różne. To Trawa w klasie Krowa i Mięso w klasie Tygrys vs. Jedzenie w klasie Zwierzę, która jest superklasa i wszystkie podklasy muszą być zgodne.
Wracając do abstrakcji typów, korzystając z poniższego diagramu i dodając po prostu abstrakcję typu, możesz zdefiniować typ danych wejściowych zgodnie z samą podklasą.
Teraz spójrz na następujące kody:
Kompilator jest zadowolony i ulepszamy nasz projekt. Możemy karmić naszą krowę krową. Odpowiednie jedzenie i kompilator uniemożliwiają nam karmienie krowy pokarmem odpowiednim dla Tygrysa. Ale co, jeśli chcemy odróżnić rodzaj krowy1 OdpowiedniFood i krowa2 SuitabeFood. Innymi słowy, byłoby bardzo przydatne w niektórych scenariuszach, gdyby ścieżka, po której docieramy do typu (oczywiście przez obiekt), miała w zasadzie znaczenie. Dzięki zaawansowanym funkcjom w scali możliwe jest:
Typy zależne od ścieżki: obiekty Scala mogą mieć typy jako elementy członkowskie. Znaczenie typu zależy od ścieżki, której używasz, aby uzyskać do niego dostęp. Ścieżka jest określana przez odniesienie do obiektu (inaczej instancji klasy). Aby zaimplementować ten scenariusz, musisz zdefiniować klasę Grass wewnątrz krowy, tj. Cow to klasa zewnętrzna, a Grass to klasa wewnętrzna. Struktura będzie wyglądać następująco:
Teraz, jeśli spróbujesz skompilować ten kod:
W linii 4 zobaczysz błąd, ponieważ Grass jest teraz wewnętrzną klasą Cow, dlatego aby utworzyć instancję Grass, potrzebujemy obiektu krowa, który określa ścieżkę. Zatem 2 krowy dają początek 2 różnym ścieżkom. W tym scenariuszu krowa2 chce jeść tylko jedzenie specjalnie dla niego stworzone. Więc:
Teraz wszyscy są szczęśliwi :-)
źródło
Oto przykład, jak używać „type” jako aliasu:
Powyższa definicja definiuje Action jako alias typu procedur (metod), które pobierają pustą listę parametrów i zwracają Unit.
źródło