如何将Animal实例转换为Dog实例?

时间:2013-04-25 12:45:19

标签: c# oop inheritance

说我有以下课程:

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? 像这样:

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对象,并传递值,(或者有一个类型为Animal的构造函数),但这看起来很混乱。

10 个答案:

答案 0 :(得分:3)

要检查对象是否可以强制转换为类型,请使用is关键字。

Animal animal = new Dog();

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

答案 1 :(得分:3)

首先将动物创建为狗,然后检查它是否is是狗

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

答案 2 :(得分:2)

你可以用is做到这一点,但是因为你想要在任何狗身上打电话,你会发现最好使用as

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

但是你应该知道这种安排(试图确定一个值的运行时类型,以便你可以把它转换成方便的东西)通常是有充分理由的。你可以轻易地过度使用并最终检查狗,猫,鹦鹉,鱼,海龟...我相信你可以看到由此产生的混乱。

如果您的需求指向这种情况,更好的解决方案是使用访问者设计模式。

答案 3 :(得分:2)

如果Animal实例从未成为Dog实例,则投射检查无效。

您可能需要查看Decorator Pattern,这样您就可以向Dog实例添加Animal方法。基本上,DogAnimal都有IAnimal接口。 Dog类在构造函数中使用Animal实例并保留内部引用。 Dog的{​​{1}}实现只是按照它引用的IAnimal实例(允许Animal转换为Dog并且行为类似于包裹IAnimal多态性{1}}。 Animal还有其他特定于Dog的方法。

答案 4 :(得分:1)

动物永远不可能是一只狗。

制作Dog构造函数,将Animal作为参数。

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

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

答案 5 :(得分:0)

我不这样做。转换是将实例解释为作为给定类型的操作,它不会更改其类型。在您的情况下,您必须首先确定该特定数据库行中的动物类型,然后实例化正确的祖先。伪代码:

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

答案 6 :(得分:0)

你可以这样做:

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

如果你需要将它投射到后者,那么检查a是否是Dog是可取的。请参阅以下答案: Casting vs using the 'as' keyword in the CLR

答案 7 :(得分:0)

你不能把动物变成狗,它可能是一只猫!我认为你要实现的是从另一个类型为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();
}

答案 8 :(得分:0)

我会在Dog对象或某种DogFactory上创建一些静态方法,您可以将Animal作为参数传递给它,让它创建您的Dog,或者返回{ {1}}。

在那种方法中,你可以检查你的动物特征,看看你是否想要它是一只狗(4条腿,位,等等)

否则很难从创建为null的对象变为具体的Animal对象

答案 9 :(得分:0)

Kamyar是对的,因为像你自己告诉我们的那样,没有办法做到这一点

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

所以你需要在数据库中保存类型

之后,您应该将Animal更改为

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

因此您可以修改Dog

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();
        }