What would be the correct implementation while deciding over interfaces vs abstract classes?
我最近遇到了一个与类创建/建模相关的问题。
把动物王国作为阶级模型。使用类创建各种表示为虚拟动物园的对象。在这个虚拟动物园中添加20只动物(在程序的主要方法中),让每只动物都发出声音。这不应该是20种不同的物种)。
我考虑了这个问题,决定使用抽象类动物而不是界面。然后我又增加了两类,鸟类,哺乳动物,它们是由动物遗传的。
我的实施
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | public abstract class Animal{ abstract Sound MakeSound(); } public class Bird : Animal { private Sound _sound; public Bird(Sound sound){ _sound = sound; } public Sound MakeSound(){ return _sound; } } //same as above with Mammals public class Program { Animal crow = new Bird("Crow sound"); Console.WriteLine(crow.MakeSound()); Animal dog = new Mammal("Dog sound"); Console.WriteLine(dog.MakeSound()); // and so on with other animals } |
我的问题是-
请推荐一些网上的资料,我可以在这些问题上改进。谢谢。
首先,重要的是要认识到,尽管"在一个阶级层次中模拟动物王国"是一个常见的初学者练习,并且经常用于示例中——我总是在示例中使用动物、哺乳动物、长颈鹿、老虎等——使用OO技术解决这不是一个现实的问题。它的目的只是让您通过思考一个您已经很好理解的领域来思考OO编程中的概念。
真正拥有管理动物库存软件的动物园不会建立这样的等级体系,因为它们的关注点实际上并不包括哺乳动物和鸟类的共同点。尽管动物王国的类比对于实现OO是有用的,但重要的是不要放弃这样一种信念,即现实世界层次中存在的每一个特性都必须在类层次中建模。
所以,也就是说,我其余的评论都是假设你真的想把动物王国作为一种练习来模拟。
第二,实现的基本问题是层次结构不够深或者太深。问题是哺乳动物和鸟类应该是抽象的,因为世界上没有什么东西只是哺乳动物或鸟类。你想要的是一种抽象类的鸟,它可以扩展动物,然后是一种具体的(可能是密封的!)延伸鸟的类乌鸦。
接下来要问的问题是:我真的需要哺乳动物和鸟类的水平吗?它们对我的程序有用吗?我有没有一种方法可以带走任何哺乳动物,但没有蜥蜴?如果它没用,就把它消灭,直接从动物到乌鸦。
第三,乌鸦发出的声音是"caw caw",而不是"crow sound"。-)
第四,回答你最好的问题:当你有几个不相关的东西"可以做"同一件事但有不同的实现时,你通常使用一个接口,并且你使用一个抽象类在有"是一种"关系的类之间共享实现细节。
制造一个声音是很多事情都可以做的事情,它们彼此之间是不相关的。鸟和钢琴不是同一种东西,它们有不同的机械装置,但它们都能发出声音。所以发出声音应该用一个接口来表示。鸟是一种动物,可能有共同的功能,所有的动物都是专门由鸟类。
简而言之:鸟是一种动物,所以它应该是一个子类。一只鸟可以发出声音,很多其他东西也可以,所以发出声音应该是一个接口。
您希望使用接口的原因之一是C不支持多重继承。
一般来说,我想把接口看作是一种能力或特性,而不是模型。
类似:
1 2 3 4 5 6 7 8 9 | public interface ISwimable { int SwimmingSpeed { get; set; } } public interface IWalkable { int RunningSpeed { get; set; } } |
现在,如果我有一只生活在水中的动物,我希望它能实现ISwimable,如果我有一只可以行走的动物,它的类应该实现Iwalkable,如果它能两者都实现,它将实现两者。