2013-04-25 19 views
6

sagen, dass ich die folgenden Klassen:Wie verwandle ich eine Animal-Instanz in eine Dog-Instanz?

class Animal 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
} 

class Dog:Animal 
{ 
    public void sniffBum() 
    { 
     Console.WriteLine("sniff sniff sniff"); 
    } 
} 

Wenn ich eine Instanz von Animal haben, wie ich warf ihm einen Dog? Etwas wie folgt aus:

Animal a = new Animal(); 
if (some logic to determine that this animal is a dog) 
{ 
    Dog d = (Dog)a; 
    d.sniffBum(); 
} 

Im Grunde kann ich nicht Schnittstellen verwenden. Ich werde immer ein Animal Objekt haben, das so aus meiner Datenbank kommt. Dog hat keine Parameter mehr als Animal hat nur neue Methoden.

Ich könnte nur ein neues Dog-Objekt erstellen und die Werte übergeben, (oder haben einen Konstruktor, der einen Typ Animal nimmt), aber das scheint nur chaotisch.

+1

zu verwenden, wenn alle Objekte von Typ 'Tier sind 'Sie müssen den Typ auch in Ihrer Datenbank in irgendeiner Weise speichern – WiiMaxx

+0

Einen Konstruktor zu haben, der einen Parameter vom Typ' Animal' nimmt, ist überhaupt nicht unordentlich IMO – Kamyar

+0

ist Ihre 'Animal' Klasse modifizierbar? – WiiMaxx

Antwort

2

Casting Schecks werden nicht funktionieren, wenn die Animal Instanz eine Dog Instanz nie gewesen ist.

Sie können sich die Decorator Pattern ansehen, mit der Sie Dog Methoden zu einer Animal Instanz hinzufügen können. Im Wesentlichen haben Dog und Animal beide die IAnimal Schnittstelle. Die Dog Klasse nimmt eine Animal Instanz im Konstruktor und behält eine interne Referenz.Die Dog 's IAnimal Implementierung verweist einfach auf die Animal Instanz, auf die es verweist (wodurch die Dog in IAnimal umgewandelt werden kann und sich wie die eingepackte Animal für Polymorphie verhält). Die Dog hat auch zusätzliche Methoden, die Dog-spezifisch sind.

3

Um zu überprüfen, ob ein Objekt in einen Typ umgewandelt werden kann, verwenden Sie das Schlüsselwort is.

Animal animal = new Dog(); 

if(animal is Dog) 
{ 
    //your code 
} 
+0

Siehe MSDN-Dokumentation über Operator ist http://msdn.microsoft.com/en-us/library/scekt9xw(v=vs.71).aspx Das ist Betreiber zu prüfen, ob der Laufzeittyp verwendet eines Objekts ist kompatibel mit einem bestimmten Typ. –

+1

Ich bin neugierig auf den Grund – zerkms

+0

@zerkms mich auch. –

0

Ich arbeite nicht so. Casting ist eine Operation, interpretiert eine Instanz als den angegebenen Typ, wird es nicht ändern sein Typ. In Ihrem Fall müssen Sie zunächst feststellen, welche Art von Tier in dieser bestimmten Datenbankzeile vorhanden ist, und dann den richtigen Vorfahren instanziieren. Pseudo-Code:

var row = Fetch from database; 
Animal animal; 
if (row is a dog) animal = new Dog(); 
else if (row is a cat) animal = new Cat(); 
2

Sie können mit is tun, aber da Sie etwas auf irgendwelchen Hunde anrufen gehen wollen Sie es besser finden würde as zu verwenden:

var dog = a as Dog; 
if (dog != null) 
{ 
    dog.sniffButt(); 
} 

aber Sie sollten Beachten Sie, dass diese Anordnung (die versucht, den Laufzeittyp eines Werts zu bestimmen, so dass Sie ihn auf etwas Bequemes anwenden können) in der Regel aus gutem Grund verpönt ist. Du könntest es leicht übertreiben und am Ende nach Hunden, Katzen, Papageien, Fischen, Schildkröten suchen ... Ich bin mir sicher, dass du dir das Chaos vorstellen kannst.

Wenn Ihre Anforderungen auf dieses Szenario hinweisen, ist die Verwendung des Visitor-Entwurfsmusters eine viel bessere Lösung.

3

erstes Tier erzeugen, wie ein Hund dann prüfen, ob es is ein Hund

Animal a = new Dog(); 
if (a is Dog) 
{ 
    Dog d = (Dog)a; 
    d.sniffBum(); 
} 
0

Sie können kein Tier in einen Hund werfen, es könnte eine Katze sein! Ich denke, was Sie erreichen möchten, ist ein Objekt des Typs Dog von einem anderen Objekt des Typs Animal, das aus db abgerufen wurde, zu erstellen.

Eine Möglichkeit ist, ein Objekt vom Typ Animal in Dog ‚s überladenen Konstruktor akzeptieren:

class Dog:Animal 
{ 
    public Dog(Animal animal) 
    { 
     this.Id = animal.Id; 
     this.Name = animal.Name; 
    } 
... 
} 

Auf diese Weise können Sie einfach das folgende verwenden:

if (some logic to determine that this animal is a dog) 
{ 
    Dog d = new Dog(a); 
    d.sniffBum(); 
} 
0

ich einige statische schaffen würde Methoden auf einem der Dog Objekt oder eine Art von DogFactory, wo Sie Ihre Animal als Parameter und lassen Sie es Ihren Hund erstellen, oder null zurückgeben können.

Bei diesem Verfahren Sie Kontrollen auf Ihren Tieren Eigenschaften tun können, um zu sehen, wenn Sie es ein Hund (4 Beine, Bits, was auch immer) sein wollen

Sonst wäre es schwer, von einem Objekt als Animal erstellt gehen zu einem Beton Dog Objekt

1

Ein Tier kann nie ein Hund sein.

Machen Sie Ihren Dog-Konstruktor und nehmen Sie ein Tier als Parameter.

class Dog : Animal 
{ 
    public Dog(Animal a) 
    { 
     this.Name = a.Name; 
     this.Id = a.Id; 
    } 

    public void sniffBum() 
    { 
     Console.WriteLine("sniff sniff sniff"); 
    } 
} 
+0

+1. Das hat das OP versucht zu erreichen – Kamyar

0

Kamyar ist richtig, es keine Möglichkeit, dies wie Sie da zu tun ist, sich selbst sagte uns

i will always have an Animal object coming out of my database like that 

so müssen Sie die Art speichern auch in Ihrer Datenbank

nach, dass Sie ändern sollten Ihre Animal bis

public class Animal 
{ 
    public long Id { get; set; } 
    public string Name { get; set; } 
    public string AnimalType { get; private set; } 

    public Animal() { } 
    public Animal(string type) 
    { 
     AnimalType = type; 
    } 

    // to denie self repeading if all animales have the same Properties 
    protected void set(Animal a) 
    { 
     Id = a.Id; 
     Name = a.Name; 
     AnimalType = a.AnimalType; 
    } 
} 

.

Dog doesnt have any more parameters than Animal has, only new methods 

so können Sie Ihre Dog zu

public class Dog : Animal 
{ 
    public Dog(Animal a) 
    { 
     base.set(a); 
    } 

    public void sniffBum() 
    { 
     Console.WriteLine("sniff sniff sniff"); 
    } 
} 

Modifié.

i could just create a new Dog object, and pass the values accross, (...), but this just seems messy 

i dort nicht denken, ein Weg, um ist, und es sieht nicht so chaotisch

und hier das, wie zB

 Animal a = new Animal("Dog"); 
     if (a.AnimalType =="Dog") 
     { 
      Dog d = new Dog(a); 
      d.sniffBum(); 
     } 
Verwandte Themen