说我有以下课程:
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
的构造函数),但这看起来很混乱。
答案 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
方法。基本上,Dog
和Animal
都有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();
}