2017-03-06 3 views
0

zu erweitern Zum Beispiel habe ich Klasse Tier und Klasse Katze (Vogel, Hund, Fisch ...), die Animal erweitert. Jetzt möchte ich die Klasse Pet deklarieren, die auch Tier ist, und ich möchte, dass sie aus jedem existierenden Tier, z.B. Katze.Ist es möglich, Instanz der Klasse

Also ich brauche Konstruktor wie folgt aus:

class Pet extends Animal{ 
    private String nickname; 
    private Animal kind; 

    Pet(Animal a, String nickname){ 
     <...>; 
     this.nickname = nickname; 
    } 
} 

EDIT: ich so etwas wie dies wollen:

Cat cat = new Cat(); 
Animal pet = new Pet(cat, "Foo"); 
if (pet instanceof Pet){ 
    if (pet.kind instanceof Cat){ 
     Pet.sayMeow(); 
    } 
} 

Ist das bedeutet, dass ich brauche Animal() nur (was geschützt ist) Konstruktor in < ...>?

+3

Fragen Sie sich: Was soll 'Pet' mit dem übergebenen' Tier' machen? Sie tun derzeit nichts damit, deshalb ist diese Frage unklar (unklar, was Ihr Grund für die Übergabe von "Tier" ist). – Tom

+0

Was @Tom sagte: einige weitere Informationen über das, was Sie erreichen möchten, wären nett. Momentan klingt das nach etwas, für das man eine 'Schnittstelle' verwenden könnte. – domsson

+2

Wenn Sie sagen, dass Sie eine vorhandene Instanz von "Animal" verwenden und diese Instanz ** rückwirkend in ein "Pet" konvertieren möchten, können Sie das nicht tun. Sie können ein neues "Pet" erstellen, das von einer "Animal" -Instanz initialisiert wird, aber es wird separat sein. Die Klasse einer Instanz ist beim Erstellen gesperrt. (Wir können verschiedene Ansichten von [interfaces to] dieser Instanz haben, einige Code wissen vielleicht nur, dass es ein 'Animal' ist und anderer Code kann wissen, dass es ein' Cat' ist, aber die * instance * hat eine bestimmte Klasse, wenn sie erstellt wird.) –

Antwort

1

Auch nach Ihrer Bearbeitung sind mir Ihre Absichten nicht wirklich klar. Es scheint so, als ob du einfach nur einen Weg suchst, der dir zur Laufzeit erlaubt zu sagen: "Diese Katze war schon mal ein Streuner, aber sie wurde gerade jemandes Haustier!".

Wenn das stimmt, dann Sie für eine sehr einfach und geradlinig Lösung gehen könnten - diese Funktion hinzufügen Recht auf Animal Klasse:

public class Animal { 

    private boolean isPet = false; 
    private String nickname = ""; 

    public Animal() { 
    /*...*/ 
    } 

    public makeStray() { 
    isPet = false; 
    nickname = ""; 
    } 

    public makePet(String nickname) { 
    isPet = true; 
    this.nickname = nickname; 
    } 

    public boolean isPet() { 
    return isPet; 
    } 

    public void makeNoise() { 
    /* Override in child classes */ 
    } 

} 

Nach Ihrem Beispiel könnten Sie dann einfach tun:

Animal cat = new Cat(); 
cat.makePet("Foo"); 
if (cat.isPet()) { // Apparently, only pet cats ever meow. 
    cat.makeNoise(); // Cats will meow, dogs will bark, ... 
} 

Beachten Sie jedoch, dass diese Art der Codierung eine Klasse schnell aufblähen kann. Es hängt wirklich davon ab, was Sie damit anders machen. Ich würde sagen, das ist die schnelle 'n' schmutzige Lösung.

Für komplexere Lösungen, überprüfen Sie die anderen Antwort (en).

EDIT1: Wie FILDOR richtig ausgeführt hat, ein Verfahren mit sayMeow() ist nicht so eine gute Idee. Bessere haben eine makeNoise() Methode in Animal und überschreiben Sie es in den untergeordneten Klassen, um das spezifische Verhalten für die verschiedenen Arten von Tieren zu erhalten. Wenn Sie jetzt nie eine Instanz der Klasse Animal erstellen möchten, können Sie auch die Klasse abstract sowie die makeNoise()-Methode erstellen. Dies würde sicherstellen, dass jede untergeordnete Klasse die Methode makeNoise() implementieren muss. Oder es geht Ihnen gut mit dem Standardverhalten von stummgeschalteten Tieren, wenn die Methode nicht überschrieben wird.

EDIT2: This answer zu einer verwandten Fragen könnte mehr Licht auf Ihre Situation werfen. Es geht um C#, aber die Prinzipien werden in Java übersetzt.

+0

Ich habe meinen Schnitt so reedited, jetzt zeigt er richtig was ich will – Noqrax

+0

Nicht wirklich. Sie haben uns Code gezeigt, den Sie arbeiten möchten, aber nicht die * Absicht * dahinter. Wenn ich es richtig lese, lautet die Intention: "Ich möchte in der Lage sein zu sagen, ob ein bestimmtes Tier ein Haustier ist oder nicht und darauf basierende Maßnahmen ergreifen". Das wäre mit dem oben gezeigten Code möglich. – domsson

0

Was Sie beschreiben, ist perfekt möglich und allgemein bekannt als "Decorator Pattern".

Link-Only-Antworten sind schlecht, ich werde später erarbeiten, wenn ich mehr Zeit habe.

Unterdessen hat Wikipedia mehr Info: Decorator Pattern.


1 Cat cat = new Cat(); 
2 Animal pet = new Pet(cat, "Foo"); 
3 if (pet instanceof Pet){ 
4 if (pet.kind instanceof Cat){ 
5   Pet.sayMeow(); 
6 } 
7 } 

Dies hat den Nachteil, dass Sie instanceOf verwenden müssen. Normalerweise würden Sie Ihre Animal Klasse eine Methode haben - nennen wir es makeNoise. Wahrscheinlich abstrakt. Sie Tier-Implementierungen (Cat, Dog ...) würde dann diese Methode überschreiben, um ihr entsprechendes Geräusch ("Bark", "Miow" ...) zu machen.

In dem Ausschnitt scheint es, dass nur Haustiere Geräusche machen können ... das macht es ein bisschen komplizierter, weil es verschiedene Möglichkeiten gäbe, dies zu tun.

Sie könnten den Dekorator einen Ton speichern lassen und das makeNoise überschreiben, um diesen Ton zu erzeugen. Wie so:

Cat catInstance = new Cat(); 
catInstance.makeNoise(); // Default impl: NOP => "" - no sound. 
Animal pet = new Pet(catInstance, "Mieow"); 
pet.makeNoise(); // => "Mieow" 

Der Punkt, der all dies ist: Sie wollen mit instanceof vermeiden. Es ist dir egal, ob das Tier eine Katze, ein Hund, eine Haustier-Katze oder ein Haustier-Hund ist. Sie müssen ihre korrekten Töne machen, wenn und wenn sie dazu aufgefordert werden. Also könntest du eine Sammlung von "Tier" s haben und sie alle an "makeNoise" erzählen und jeder wird still bleiben, bellen oder sich umschauen, ohne dass du dich darum kümmern musst, ob es Haustiere sind oder welches spezielle Kind von Animal.

BEARBEITEN: Lesen meine Antwort wieder, es ist eher wie eine Politik (Strategie Muster) als ein Dekorateur. Die Richtlinie ändert, wie etwas ausgeführt wird, während der Dekorator die Funktion hinzufügen würde.

Also ein echter Dekorator zu sein, würde bedeuten, dass makeNoise in der Schnittstelle von Pet wäre. Was bedeutet, dass Sie diese Methode nicht bei Animals aufrufen können.

Deshalb ändere ich meinen Vorschlag von "Decorator" zu "Strategy" Muster.

Das obige Beispiel gilt immer noch. Sie haben eine "Standard" -Strategie und injizieren die "Pet" -Strategie mit einem Decorator-ähnlichen Implementierungsansatz.

Natürlich könnte das alles auch anders gemacht werden, um das Muster strenger zu implementieren.

Endlich klingelt if(x instanceof X) ... immer noch die "Visitor" -Bell, auch.

+0

Guter Fang auf der 'makeNoise()' - vollständig ignoriert, dass zuvor. Jetzt habe ich meine Antwort entsprechend bearbeitet. – domsson

Verwandte Themen