2015-07-15 29 views
5

Ostatnio dlangowałem w Dlang, ponieważ C++ po prostu nie pasowało do mnie po tak długim użyciu Pythona. Podczas omszania natknąłem się na to, co uważam za bardzo proste ćwiczenie polimorfizmu. Przypuszczam, że spodziewałbyś się, że coś zadziała, a to, co faktycznie robi, to dwie zupełnie różne rzeczy z powodów, których użytkownik końcowy prawdopodobnie nie jest w stanie pojąć. Mając na uwadze powyższe, tutaj jest kod źródłowy mojego „sandbox.D”:Dlaczego ta metoda podklasy nie jest polimorficzna?

import std.stdio; 

class Animal { 
    string voice = "--silence--"; 
    void speak() { 
     writeln(this.voice); 
    } 
} 

class Dog : Animal { 
    string voice = "Whoof!"; 
} 

int main() { 
    auto a = new Animal(); 
    auto d = new Dog(); 

    writeln(a.voice); // Prints "--silence--" 
    writeln(d.voice); // Prints "Whoof!" 

    a.speak(); // Prints "--silence--" 
    d.speak(); // Prints "--silence--" NOT "Whoof!" 

    return 0; 
} 

Chyba mój problem jest, dlaczego „to” słowo kluczowe po prostu nie wydają się być działa jak można oczekiwać, że w język następcy C++.

Odpowiedz

5

Metody są polimorficzne, zmienne nie. Zamiast więc zmienić wartość głosu, chcesz mieć dziecko w postaci override speak.

Również typ zwracany nie działa z polimorfizmem, trzeba właściwie określić typy. (Powód jest taki, że funkcja automatycznego powrotu tworzy szablon funkcji w kompilatorze, który teoretycznie może mieć wiele zastępowalnych gniazd w tabeli funkcji, więc po prostu nie próbuje go wstawić.)

Wypróbuj to:

import std.stdio; 

class Animal { 
    void speak() { // changed to void instead of auto 
    writeln("--silence--"); 
    } 
} 

class Dog : Animal { 
    override void speak() { // the override tells it to override the base method 
    writeln("woof"); 
    } 
} 

int main() { 
    auto d = new Dog(); 
    d.speak(); 
    return 0; 
} 

Jeśli masz dużo wspólnego funkcjonalności i chcą ponownie wykorzystać jedną funkcję z niewielkimi zmianami w klasach potomnych, można dokonać metodą zamiast zmiennej, która właśnie wraca coś.

Podobnie jak string voice() { return "woof"; }, może być nadpisany u dzieci.

+0

Ah, doceniam taką szybką reakcję! Zastanawiałem się, czy usunąć niektóre słowa kluczowe "auto". Ostatecznie, wypróbowałem to bez auto i zadeklarowałem właściwe typy, ale to nie miało znaczenia. Sądzę, że dziedziczenie obiektowe nie wydaje się tak przydatne, jak sobie wyobrażałem :( –

+2

Przydaje się, po prostu pamiętaj, że tylko metody są nadpisywalne, zmienne nie. (Nie jestem pewien, czy to samo w Python, ale generalnie działa w ten sposób w wielu językach OOP), choć dziedziczenie ma swoje ograniczenia, możesz rozwiązać wiele rzeczy za jego pomocą, ale nie zawsze jest to najlepszy sposób: –

+0

Jest bardzo przydatny. Musisz tylko zrozumieć, jak go używać, i źle rozumiesz, jak to działa.Trzeba tylko zastąpić funkcję zamiast zmiennej członkowskiej, i działa dobrze.Kod długość nie jest nawet bardzo różne.I jeśli chcesz zastąpić zmienną składową, po prostu zapakuj ją w funkcję, aby zwrócić jej wartość i użyj funkcji zamiast bezpośrednio używać zmiennej.Ale nigdy nie słyszałem o języku, który przeładowałby zmienne i biorąc pod uwagę sposób działania polimorfizmu pod maską, oznaczałoby to w zasadzie wrappi I tak w funkcjach pod maską. –

1

Innym sposobem jest użycie szablon ten parametr:

import std.stdio; 

class Animal { 
    string voice; 

    void speak(this C)() { 
     writeln((cast(C)this).voice); 
    } 
} 

class Dog : Animal { 
    string voice = "Whoof!"; 
} 

int main() { 
    auto a = new Animal(); 
    auto d = new Dog(); 

    a.speak(); // Prints "" 
    d.speak(); // Prints "Whoof!" 

    return 0; 
} 

Albo kiedy nie trzeba mieć głos na stanowisko członka:

import std.stdio; 

class Animal { 
    static immutable voice = ""; 

    void speak(this C)() { 
     writeln(C.voice); 
    } 
} 

class Dog : Animal { 
    static immutable voice = "Whoof!"; 
} 

int main() { 
    auto a = new Animal(); 
    auto d = new Dog(); 

    a.speak(); // Prints "" 
    d.speak(); // Prints "Whoof!" 

    return 0; 
} 
+0

Dziękuję za odpowiedź. Główny ciężar mego zamieszania polegał właśnie na tym, że "nie" odnosiło się do głosu Psa, lecz do podstawowego zwierzęcego głosu. Sądzę, że właściwości nie są takie same w Dlang, jak myślałem, że będą :) –