【发布时间】:2011-09-03 02:37:44
【问题描述】:
我在与多态类型(甚至多态接口)交互的接口概念上遇到了麻烦。我正在使用 C# 进行开发,并希望得到与此定义保持接近的答案,尽管我认为这仍然为每个人提供了足够的空间来提出答案。
举个例子,假设您想编写一个程序来绘制事物。您为绘制的actor定义一个界面,并为绘制的主题定义一个界面,此外,您还有一些可以以更具体的方式绘制的主题。
interface IPainter {
void paint(IPaintable paintable);
}
interface IPaintable {
void ApplyBaseLayer(Color c);
}
interface IDecalPaintable : IPaintable {
void ApplyDecal(HatchBrush b);
}
我可以想象制作一个类似于以下内容的画家:
class AwesomeDecalPainter : IPainter
{
public void paint(IPaintable paintable) {
IDecalPaintable decalPaintable = (IDecalPaintable)paintable;
decalPaintable.ApplyBaseLayer(Color.Red);
decalPaintable.ApplyDecal(new HatchBrush(HatchStyle.Plaid, Color.Green));
}
}
当然,如果paintable 没有实现IDecalPaintable,这将抛出。它立即引入了 IPainter 实现和它所操作的 IPaintable 之间的耦合。但是,我也认为说 AwesomeDecalPainter 不是 IPainter 只是因为它的使用仅限于 IPaintable 域的子集是没有意义的。
所以我的问题实际上有四个方面:
- 接口是否兼容 多态性?
- 好不好 设计实现一个IPainter 可以在 IDecalPaintable 上操作吗?
- 如果可以独占怎么办 在 IDecalPaintable 上?
- 是否有任何文献或源代码 举例说明接口和多态类型如何 应该互动吗?
【问题讨论】:
-
IDecalPainter.paint是一个糟糕的设计的原因,请参阅"What is the Liskov Substitution Principle?"。你应该拥有的是一个重载的paint,它需要一个IDecalPaintable,以便AwesomeDecalPainter可以同时接受IPaintables 和IDecalPaintables。 -
... 一个
IPainter应该能够在任何IPaintable上paint。说AwesomeDecalPainter不是IPainter是完全有道理的,因为它不能在所有IPaintables 上运行。见circle-ellipse problem,也称为square-rectangle problem -
似乎不可能说 IPainter 应该能够在 some IPaintable 上进行绘画,但该语言直接促进了这种用法。也许接口可以安全地对多态类型进行操作,但接口本身不能是多态的。
-
只要你支持IPaintable,你可以添加任何你想要的东西。您的界面所说的是,任何作为 IPainter 的人也可以在任何对 ApplyBaseLayer 是 IPaintable 的基板上进行操作。这意味着我可以让任何人出现,从贫民区的孩子到伦勃朗的学徒,只要他们是 IPainter,我可以给他们任何东西,从画布到砖墙,只要是 IPaintable,他们可以应用BaseColor。时期。他们还能做什么就是他们能做什么。它不是由 IPainter 和 IPaintable 定义的,作为我不认识或不关心的客户。
-
@SmokingRope:接口不是多态的,因为它们没有任何方法;他们只定义方法签名。它们支持多态性,因为实现相同接口的不同类可以有自己的方法实现,但都具有具有相同签名的相同方法。使用仅适用于
IDecalPaintable的IPaintable参数定义paint方法不仅会破坏 Liskov 替换原则,还会破坏类型系统。
标签: c# .net oop interface polymorphism