在C#中,我有三个类:Person,Cat和Dog.
Cat和Dog类都有方法Eat().
我希望Person类有一个属性'Pet'.
我希望能够通过Person之类的Person.Pet.Eat()调用Cat和Dog的Eat方法,但我不能,因为Pet属性需要是Cat或Dog类型.
目前我正在使用Person类中的两个属性:PetDog和PetCat.
现在这没关系,但如果我想要100种不同类型的动物作为宠物,那么我真的不想在Person类中拥有100种不同的Pet属性.
有没有办法使用接口或继承?有没有办法可以将Pet设置为Object类型,但仍然可以访问分配给它的动物类的属性?
Dar*_*rov 12
你可以让宠物从一个共同的基类派生出来:
public abstract class Animal
{
protected Animal() { }
public abstract void Eat();
}
Run Code Online (Sandbox Code Playgroud)
然后Cat和Dog派生自这个基类:
public class Cat: Animal
{
public override void Eat()
{
// TODO: Provide an implementation for an eating cat
}
}
public class Dog: Animal
{
public override void Eat()
{
// TODO: Provide an implementation for an eating dog
}
}
Run Code Online (Sandbox Code Playgroud)
你的Person类将有一个类型的属性Animal:
public class Person
{
public Animal Pet { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
当你有一个Person实例时:
var person = new Person
{
Pet = new Cat()
};
// This will call the Eat method from the Cat class as the pet is a cat
person.Pet.Eat();
Run Code Online (Sandbox Code Playgroud)
您还可以为Eat基类中的方法提供一些常用实现,以避免在派生类中重写它:
public abstract class Animal
{
protected Animal() { }
public virtual void Eat()
{
// TODO : Provide some common implementation for an eating animal
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,Animal它仍然是一个抽象类,以防止它直接实例化.
public class Cat: Animal
{
}
public class Dog: Animal
{
public override void Eat()
{
// TODO: Some specific behavior for an eating dog like
// doing a mess all around his bowl :-)
base.Eat();
}
}
Run Code Online (Sandbox Code Playgroud)
Eri*_*ert 11
有没有办法使用接口或继承?
是.
接口:创建IEat或IPet接口或您想要表示的任何概念.使接口具有Eat方法.让Cat和Dog实现此界面.让Pet属性属于那种类型.
继承:创建一个抽象基类Animal或Pet或您想要表示的任何概念.在基类上创建一个抽象方法Eat.让猫和狗继承这个基类.让Pet属性属于那种类型.
这两者有什么区别?
使用接口来模拟"X知道如何做Y"的想法.例如,IDisposable意味着"我知道如何处置我所持有的重要资源".这不是关于对象是什么的事实,它是关于对象做什么的事实.
使用继承来模拟"X是一种Y"的概念.狗是一种动物.
关于接口的事情是你可以拥有任意数量的接口.但是你只能直接从一个基类继承,所以如果你要使用继承,你必须确保你做对了.继承的问题是人们最终制作像"车辆"这样的基础类,然后他们说"一辆军车是一种车辆"和"一艘船是一种车辆",现在你被卡住了:什么是基础毁灭者的类?它既是船只又是军用车辆,它不能同时存在.非常仔细地选择你的"继承支点".
有没有办法可以将Pet设置为Object类型,但仍然可以访问分配给它的动物类的属性?
是的,在C#4中有,但不要这样做.使用接口或继承.
在C#4中,您可以使用"dynamic"在运行时动态调度到Pet中对象的Eat方法.
你不想这样做的原因是因为如果有人在Pet属性中放入Fruit或Handsaw然后尝试将其变为Eat,这将会崩溃并且可怕地死亡.编译时检查的目的是减少程序的脆弱性.如果您有办法进行更多的编译时检查,请使用它.
| 归档时间: |
|
| 查看次数: |
299 次 |
| 最近记录: |