简体   繁体   English

关于对象设计的说明

[英]Clarification regarding the object design

I have a doubt when is it apt to use an Interface and when to use inheritance in OO design. 我怀疑何时在OO设计中易于使用接口以及何时使用继承。 Lets say I have a human class and it inherits from the Mammal class. 可以说我有一个人类阶级,它是从哺乳动物阶级继承而来的。 The Mammal class will have instance variables like eyes, nose, ears and limbs. 哺乳动物类将具有实例变量,例如眼睛,鼻子,耳朵和四肢。 My question is whether the eat method should go inside the Mammal class or it should be in an Interface. 我的问题是eat方法应该在Mammal类中还是应该在Interface中。 I thought the eat, sleep, breathe method should go inside an Interface. 我认为饮食,睡眠和呼吸方法应该放在接口内部。 Please let me know if my OO design is correct and the reasoning if my understanding is wrong. 请让我知道我的面向对象设计是否正确,如果我的理解不正确,请告诉我。

My question is whether the eat method should go inside the Mammal class or it should be in an Interface. 我的问题是eat方法应该在Mammal类中还是应该在Interface中。

Why can't it be both in an interface and in the base class? 为什么不能同时在接口基类中使用它?

(Note that I'm not 100% an expert on the mechanics of Java and don't know for certain how it would be implemented in code. This is a language-agnostic answer about object oriented design.) (请注意,我不是100%的Java专家,也不知道如何在代码中实现。这是关于面向对象设计的语言不可知的答案。)


An interface and a base class aren't interchangeable things, as the wording of your question seems to almost imply. 接口和基类是不可互换的,因为您的问题的措辞似乎几乎暗示了这一点。 They serve two very different purposes. 它们有两个截然不同的目的。

An interface is a kind of contract of functionality. 接口是一种功能契约。 It's a set of operations which can be implemented by an object. 这是一组可由对象实现的操作。 A base class, on the other hand, is a concrete type of what that object is. 另一方面,基类是该对象的具体类型。 To think of it in a vague pseudo-analogy... 用模糊的伪类想起来...

An interface tells you what something can do. 界面告诉您可以做什么。 A base type tells you what something is. 基本类型告诉您什么是什么。

Consider your example... Mammal and Human. 考虑你的例子……哺乳动物和人类。 Now, clearly, Mammal must be an abstract type. 现在,很明显,哺乳动物必须是抽象类型。 You can't have a generic "mammal" knocking about in the world, it has to be a species of some kind. 世界上不可能有通用的“哺乳动物”在敲门,它必须是某种物种。 And consider that all mammals eat in some way. 并考虑到所有哺乳动物都以某种方式进食。

Do all mammals eat the exact same way? 所有哺乳动物都以完全相同的方式进食吗? If so, then you can create a single implementation of eat() on the abstract base class and all inheriting types would use it. 如果是这样,则可以在抽象基类上创建eat()的单个实现,并且所有继承类型都将使用它。

Do most mammals eat the exact same way, but there are some exceptions? 大多数哺乳动物是否以完全相同的方式进食,但是有一些例外吗? If so, then you can still create that base implementation of eat() but allow inheriting types to override it in their own implementations if they choose to do so. 如果是这样,那么您仍然可以创建eat()基本实现,但是允许继承类型在自己的实现中覆盖它们(如果他们选择这样做)。

Do most or all mammals eat in entirely different ways, but all eat somehow? 大多数或所有哺乳动物以完全不同的方式进食 ,但全部以某种方式进食吗? If so, then you'd likely want to create an abstract eat() method signature in the base class and require that inheriting types implement it. 如果是这样,那么您可能想在基类中创建一个抽象的eat()方法签名,并要求继承类型实现它。


Ok, so where do interfaces come in? 好的,接口从何而来?

Well, mammals aren't the only things that eat. 好吧,哺乳动物不是唯一可以吃的东西。 Birds eat. 鸟吃。 Lizards eat. 蜥蜴吃。 Plants eat. 植物吃。 Robots eat. 机器人吃饭。 Fire eats. 火吃。 etc. 等等

Lots of things eat. 吃很多东西。 Not just mammals and their descendant types. 不只是哺乳动物及其后代类型。 Not even just their ancestor types. 不仅是他们的祖先类型。 Not even just types that are remotely related to mammals in any way. 甚至不仅仅是与哺乳动物有任何远程联系的类型。 (Fire, for example.) So the concept of "eating" is orthogonal to the type hierarchy in your inheritance for mammals. (例如,火灾。)因此,“进食”的概念与哺乳动物继承中的类型层次正交。

In order to group together these implementations which aren't related via an inheritance model (or at least aren't guaranteed to be), you'd define an interface. 为了将通过继承模型不相关(或至少不能保证是不相关)的这些实现组合在一起,您需要定义一个接口。

Suppose you have an operation which simply wants to feed an object. 假设您有一个仅想馈送对象的操作。 While other parts of the system may care whether or not that object is a mammal, or an animal of any kind, or even just a living thing of any kind... this operation does not. 尽管系统的其他部分可能会在乎该对象是哺乳动物还是任何种类的动物,甚至只是任何种类的生物……此操作都不会。 It just cares that the object can, in some way, eat. 它只是在乎物体可以以某种方式进食。 A robot or a fire or some other non-living thing could satisfy this requirement. 机器人,火或其他非生命物体可以满足此要求。 This operation would declare that it expects an Eater , not a Mammal . 这个行动将宣告它期待一个Eater ,而不是Mammal

So somewhere in your abstract hierarchy of base types (living thing, animal, mammal, etc.) one of those types (probably the top-level one in this example) declares that it implements an Eater interface. 因此,在基本类型(生物,动物,哺乳动物等)的抽象层次结构中的某个位置,这些类型之一(在此示例中可能是顶级类型)声明实现了Eater接口。 This would enforce that all inheriting types must also implement that interface. 这将强制所有继承类型也必须实现该接口。

If there's an abstract higher-level implementation which is inherited by the descendant type, then the interface is satisfied. 如果存在由后代类型继承的抽象的更高级别的实现,则满足该接口。 If there isn't, then the descendant type would need to provide the implementation of eat() to satisfy the interface. 如果没有,则后代类型将需要提供eat()的实现来满足该接口。

But the point is that other things, entirely outside of this particular inheritance graph, can also implement that interface and can also eat. 但是重点是,完全不在此特定继承图之外的其他事物也可以实现该接口,也可以吃东西。

You are correct. 你是对的。 You can create an interface like Animal which will contains those methods. 您可以创建一个类似于Animal的接口,其中将包含这些方法。 In the subclasses (which implements Animal ) those methods should be implemented. 在子类(实现Animal )中,应实现这些方法。 Because eg Mammal , Reptile have their different walking technique 因为例如MammalReptile具有不同的行走技术

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM