Как превратить экземпляр животного в экземпляр собаки?

скажем, у меня есть следующие классы:

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

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

если у меня есть экземпляр Animal, как мне бросить его в Dog? Что-то вроде этого:--10-->

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

по сути, я не могу использовать интерфейсы. У меня всегда будет Animal объект выходит из моей базы данных, как это. Dog не имеет больше параметров, чем Animal имеет, только новые методы.

я мог бы просто создать новый Dog object и передать значения через (или иметь конструктор, который принимает тип Animal), но это только кажется грязным.

10 ответов


проверка кастинга не будет работать, если Animal экземпляр никогда не был Dog экземпляра.

вы можете посмотреть на Шаблон "Декоратор", что позволит вам добавить Dog методы Animal экземпляра. По существу,Dog и Animal как есть IAnimal интерфейс. The Dog класс берет Animal экземпляра в конструкторе и сохраняет внутреннюю ссылку. The Dog ' s IAnimal реализация просто откладывается на Animal экземпляр он ссылается (что позволяет Dog быть брошенным в IAnimal и вести себя как завернутый Animal полиморфизм). The Dog также имеет дополнительные методы, специфичные для собак.


сначала создайте животное как собаку, затем проверьте, если это is собака

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

чтобы проверить, может ли объект быть приведен к типу, используйте is ключевое слово.

Animal animal = new Dog();

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

С is, но так как вы хотите что-то назвать на любых собаках, которые вы найдете, было бы лучше использовать as:

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

однако вы должны знать, что это расположение (попытка определить тип времени выполнения значения, чтобы вы могли привести его к чему-то удобному) обычно неодобрительно относится к уважительной причине. Вы можете легко перестараться и в конечном итоге проверить собак, кошек, попугаев, рыб, черепах... Я уверен, что вы можете визуализировать результат беспорядок.

Если ваши потребности указывают на то, что сценарий, лучшим решением является использование шаблона разработки посетителя.


животное никогда не может быть собакой.

сделайте свой конструктор собаки, принимая животное в качестве параметра.

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

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

Я так не работаю. Кастинг-это операция, которая интерпретирует экземпляр как данный тип, он не будет изменить его тип. В вашем случае вы должны сначала определить, какое животное есть в этой конкретной строке базы данных, а затем создать экземпляр правильного предка. Псевдокод:

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

вы можете сделать это:

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

это preffereable для проверки, если собака, Если вам нужно бросить его последний. См. следующий ответ: кастинг против использования ключевого слова " as " в CLR


Я бы создал некоторые статические методы на


вы не можете разыграть животное, в собаку, это может быть кошка! Я думаю, что вы пытаетесь достичь, чтобы создать объект типа Dog, от другого объекта типа Animal Это было извлечено из db.

один из способов-принять объект типа Animal на Dogперегруженный конструктор:

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

таким образом, вы можете просто использовать следующее:

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

Камьяр прав, нет никакого способа сделать это, потому что, как вы сами сказали нам

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

поэтому вам нужно сохранить тип также в вашей базе данных

после этого вы должны изменить свой Animal to

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

так что вы можете modifie свой Dogto

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

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

.

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

Я не думаю, что есть способ обойти и это не выглядит так неопрятно

а вот как использовать пример

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