首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >接口是否与多态性兼容?

接口是否与多态性兼容?
EN

Stack Overflow用户
提问于 2011-05-27 03:49:26
回答 3查看 12.9K关注 0票数 22

在接口与多态类型(甚至多态接口)交互的概念上,我遇到了麻烦。我正在C#中开发,希望答案能保持在这个定义的附近,尽管我认为这仍然给每个人提供了足够的空间来给出一个答案。

举个例子,假设你想要制作一个程序来描绘事物。你为画家定义了一个界面,你为被描绘的主体定义了一个界面,而且你还有一些主题可以用更具体的方式来描绘。

代码语言:javascript
复制
interface IPainter {
  void paint(IPaintable paintable);
}
interface IPaintable {
  void ApplyBaseLayer(Color c);
}
interface IDecalPaintable : IPaintable {
  void ApplyDecal(HatchBrush b);
}

我可以想象,一位画家的表现如下所示:

代码语言:javascript
复制
class AwesomeDecalPainter : IPainter
  {
    public void paint(IPaintable paintable) {
      IDecalPaintable decalPaintable = (IDecalPaintable)paintable;
      decalPaintable.ApplyBaseLayer(Color.Red);
      decalPaintable.ApplyDecal(new HatchBrush(HatchStyle.Plaid, Color.Green));
    }
  }

当然,如果痛表不实现IDecalPaintable,这将抛出。它立即引入了IPainter实现与其操作的IPaintable之间的耦合。但是,我也不认为说AwesomeDecalPainter不是IPainter是有意义的,因为它的使用仅限于IPaintable域的一个子集。

所以我的问题是四方面的:

  • 的接口与多态性完全兼容?
  • 实现一个可以在IDecalPaintable上操作的IPainter好吗?
  • ,如果它可以完全在IDecalPaintable上操作怎么办?
  • ,有什么文献或源代码可以说明接口和多态类型应该如何交互?

< code >f 211

EN

回答 3

Stack Overflow用户

发布于 2011-05-27 04:10:10

类的接口意味着作为该类的“用户”的工具。接口是类的公开表示,它应该向任何考虑使用接口的人宣传哪些方法和常量是可以从外部获得和访问的。因此,顾名思义,它总是位于实现它的用户和类之间。

另一方面,抽象类是一种帮助扩展类的“实现者”的工具。它是一种基础结构,可以对具体类的外观施加限制和指导。从类设计的角度来看,抽象类在体系结构上比接口更重要。在这种情况下,实现者位于抽象类和具体类之间,后者在抽象类的基础上构建。

因此,简单地回答你的问题,界面是代码尊重的“契约”。当使用这种方式时,它更适用于继承该多态性。

抽象类,它们定义“类型”。当具体子类使用抽象类并重新定义方法时,添加新的类等等。在这里,您可以看到多态的作用。

我知道这篇文章可能会让你更困惑,直到我学会了设计模式才有意义。有了几个简单的模式,您将更好地理解每个对象的角色,以及继承、多态性和封装如何携手构建设计清晰的应用程序。

祝你好运

票数 17
EN

Stack Overflow用户

发布于 2011-05-27 04:55:05

问题在于你已经定义了一个模糊的界面,合同是一个更合适的术语。就像你走进McDonalds,只点了一个汉堡:

代码语言:javascript
复制
interface Resturant
{
    Burger BuyBurger();
}

接受你点菜的人会有一段时间看起来有点困惑,但最终他/她会为你提供任何汉堡,因为你没有具体说明你想要什么。

这里也是一样的。你真的只想定义什么东西是可以画的吗?如果你问我,这就像自找麻烦。始终尝试使接口尽可能具体。与大型通用接口相比,拥有几个小的特定接口总是更好。

但让我们回到你的例子。在您的情况下,所有的类只需要能够绘制一些东西。因此,我要添加另一个更具体的接口:

代码语言:javascript
复制
    interface IPainter
    {
        void Paint(IPaintable paintable);
    }
    interface IDecalPainter : IPainter
    {
        void Paint(IDecalPaintable paintable);
    }
    interface IPaintable
    {
        void ApplyBaseLayer(Color c);
    }
    interface IDecalPaintable : IPaintable
    {
        void ApplyDecal(HatchBrush b);
    }

    class AwesomeDecalPainter : IDecalPainter
    {
        public void Paint(IPaintable paintable)
        {
            IDecalPaintable decalPaintable = paintable as IDecalPaintable;
            if (decalPaintable != null)
                Paint(decalPaintable);
            else
                paintable.ApplyBaseLayer(Color.Red);
        }

        public void Paint(IDecalPaintable paintable)
        {
            paintable.ApplyBaseLayer(Color.Red);
            paintable.ApplyDecal(new HatchBrush(HatchStyle.Plaid, Color.Green));
        }
    }

我建议你读到关于坚实原则的文章。

更新

更完善的接口实现

代码语言:javascript
复制
    interface IPaintingContext
    {
        //Should not be object. But my System.Drawing knowledge is limited
        object DrawingSurface { get; set; }
    }
    interface IPaintable
    {
        void Draw(IPaintingContext context);
    }

    class AwesomeDecal : IPaintable
    {
        public void Draw(IPaintingContext paintable)
        {
            // draw decal
        }
    }

    class ComplexPaintableObject : IPaintable
    {
        public ComplexPaintableObject(IEnumerable<IPaintable> paintable)
        {
            // add background, border 
        }
    }

在这里,您可以创建尽可能复杂的绘画项目。他们现在知道他们在上面画了什么,或者在同一表面上使用了什么其他的油漆。

票数 5
EN

Stack Overflow用户

发布于 2011-05-27 04:01:11

我正确地理解了你的问题吗?

我认为您的问题是,接口是否可以行使继承的基本要素?

(即)从父接口继承子接口)。

1)如果是这样的话,在句法上是肯定的,为什么不呢?

2)至于实用性,它可能没有多大价值,因为您的子接口本质上并没有重用父接口中的任何内容。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6147658

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档