C# 接口实现关系只是“Can-Do”关系 关系?
今天有人告诉我,C# 中的接口实现只是“Can-Do”关系,而不是“Is-A”关系。 这与我长期以来所相信的LSP(里氏替换原理)相冲突。 我一直认为所有的继承都应该意味着“Is-A”关系。
所以,如果接口实现只是一种“Can-Do”关系。 如果有一个接口“IHuman”和“IEngineer”,并且一个类“Programmer”继承自“IHuman”和“IEngineer”怎么办? “我工程师”? 当然,“程序员”是“IHuman”和“IEngineer”。
如果这只是“Can-Do”关系,是否意味着我们不能期望“程序员”实例行为在被视为 IHuman 和被视为 IEngineer 时可能有所不同?
Today somebody told me that interface implementation in C# is just "Can-Do" relationship, not "Is-A" relationship. This conflicts with my long-time believing in LSP(Liskov Substitution Principle). I always think that all inheritance should means "Is-A" relationship.
So, If interface implementation is just a "Can-Do" relationship. What if there is a interface "IHuman" and "IEngineer", and one class "Programmer" inherits from "IHuman" & "IEngineer"? Surely, a "Programmer" Is A "IHuman" and A "IEngineer".
If it is just "Can-Do" relationship, does it mean we cannot expect the "Programmer" instance behavior may be different between when treated as a IHuman and treated as IEngineer?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
很晚才发现这个问题,但我想插话。C
# 中的接口有 is-a 关系,但不是 is-an-object 关系。 相反,是一种实现。
换句话说,对于实现 IBar 的类 Foo,以下测试:
字面上返回 true。 你也可以说,
或者,如果一个方法需要 IBar,你可以传递 Foo。
显然,IBar 本身没有实现,因此 can-do 关系也适用。
但是,就此而言,对象继承也是如此。 继承类 Bar 的类 Foo 的对象具有 can-do 关系以及 is-a 关系,与接口的方式相同。 只是它的实现是为其预先构建的。
真正的问题是,is-a-what,can-do-what? 继承的类对象是-[父实例]并且可以-[父的行为],而接口的实现是-[接口实现],因此可以-[接口行为]。
在大多数使用编程 is-a 关系(例如上面列出的关系)的情况下,仅评估接口,因此继承的类和实现的接口都共享相同的 is-a 和 can-do 品质。
哈特哈,
乔恩
Found this question rather late but I wanted to chime in.
Interfaces in C# have an is-a relationship, but not is-an-object. Rather, is-an-implementation.
In other words, for class Foo that implements IBar, the following test:
literally returns true. You can also say,
Or, if a method requires an IBar, you can pass a Foo.
Obviously, an IBar has no implementation in itself, so the can-do relationship also applies.
But, for that matter, the same is true of object inheritance; an object of class Foo that inherits class Bar has a can-do relationship as well as an is-a relationship, in the same way as the interface does. It's just that its implementation was pre-built for it.
The real question is, is-a-what, can-do-what? An inherited class object is-a-[parent instance] and can-do-[parent's behavior], whereas an implementation of an interface is-an-[interface implementation] and therefore can-do-[the interface behavior].
In most cases where programmatic is-a relationships are used such as those listed above, only the interface is evaluated, so both an inherited class and an implemented interface share the same is-a and can-do qualities.
HTH,
Jon
.NET 框架的设计者使用接口来指定“有一个”(或“可以做”)关系,而“是一个”是使用继承来实现的。
其基本原理可以在在类和接口之间进行选择中找到.NET Framework 开发人员指南的部分:
因此,由于您的“程序员”和“工程师”示例类很可能具有自己的特定功能,因此使用继承来实现它们会更合适。
The designers of the .NET framework use interfaces to designate a "has a" (or "can do") relationship, whereas "is a" is implemented using inheritance.
The rationale for this can be found in the Choosing Between Classes and Interfaces section of the .NET Framework Developer's Guide:
So, since your "Programmer" and "Engineer" example classes would most likely come with their own specific functionality, they would be more suitably implementated using inheritance.
实际上,这就是为什么大多数接口都是功能而不是名称,所以你有
IComparable、ITestable、IEnumerable
和
Human、Animal、Dog 等
无论如何,正如已经提到的,你必须务实,我有一个一般规则我正在编码:永远不要让概念、惯例或标准实践妨碍完成工作,最好是务实而不是学术。
因此,如果您确定界面确实更适合您的设计,那就去吧对于它,不要担心诸如此类的问题。
Actually that's why most of the interface are capabilities and not names so you have
IComparable, ITestable, IEnumerable
and
Human, Animal, Dog, etc
Anyway, as it has been already mentioned you have to be pragmatic, I've got a general rule when I'm coding: never let concepts, conventions or standard practices get on the way of getting the job done, better be pragmatic than academic.
so if you're sure interfaces really fit better your design, go for it, don't worry about question such as this one.
根据我的经验,思考“是”和“可以做”的关系并没有多大帮助。 你很快就会遇到问题。 基本上,这是现实世界和面向对象之间的阻抗不匹配。 无论有多少人实际上谈论对现实世界进行建模,您从根本上都需要了解类型之间的关系在您所使用的平台上意味着什么。
有时接口可以用作功能,有时它们可以代表更多正常的“is-a”关系。 我不会太在意它——只要确保你了解他们能做什么和不能做什么就可以了。
In my experience it doesn't really help that much to think of "is-a" and "can-do" relationships. You rapidly get into problems. It's an impedance mismatch between the real world and OO, basically. However much people actually talk about modeling the real world, you fundamentally need to understand what the relationships between types mean on the platform you're using.
Sometimes interfaces can be used as capabilities, and sometimes they can represent more of a normal "is-a" relationship. I wouldn't get too hung up about it - just make sure you understand what they can do and what they can't.
我倾向于将接口视为行为契约。 IComparable 和 IEnumerable 等接口就是典型的例子。
在您给出的示例中,IHuman 和 IEngineer 并不是真正的行为。
I tend to think of interfaces as a contract of behaviour. Interfaces such as IComparable and IEnumerable are classic examples.
In the example you gave, IHuman and IEngineer are not really behaviours.