【问题标题】:My abstract class implements an interface but doesn't implement some of its methods. How do I make it compile?我的抽象类实现了一个接口,但没有实现它的一些方法。我如何使它编译?
【发布时间】:2011-02-07 10:31:09
【问题描述】:
interface ICanvasTool
{
    void Motion(Point newLocation);
    void Tick();
}

abstract class CanvasTool_BaseDraw : ICanvasTool
{
    protected abstract void PaintAt(Point location);

    public override void Motion(Point newLocation)
    {
        // implementation
    }
}

class CanvasTool_Spray : CanvasTool_BaseDraw
{
    protected abstract void PaintAt(Point location)
    {
        // implementation
    }

    public override void Tick()
    {
        // implementation
    }
}

这无法编译。我可以将抽象方法“Tick_Implementation”添加到 CanvasTool_BaseDraw,然后在 CanvasTool_BaseDraw 中使用仅调用 Tick_Implementation 的单行代码实现 ICanvasTool.Tick。这是推荐的解决方法吗?

【问题讨论】:

  • 当您使用界面时,我不确定您所说的“解决方法”是什么意思。接口是一个契约,因此任何实现该接口的类型都必须遵守该契约。编译器的这种强制执行是为了让你的类的调用者可以知道任何实现 ICanvasTool 的类型都有这两个方法。
  • 是的,我希望编译器强制接口的任何非抽象后代实现所有它。我只是不希望 abstract 的后代出现这种情况。
  • 顺便说一句,Java 是按照我的方式来做的。见stackoverflow.com/questions/197893

标签: c# oop interface abstract-class


【解决方案1】:

这样做的方法是在CanvasTool_BaseDraw 中添加一个抽象的void Tick() 方法并在CanvasTool_Spray 中覆盖它。

并非所有编程语言都这样做。在 Java 中,您不必为您实现的接口中的每个方法添加抽象方法。在这种情况下,您的代码将编译。

【讨论】:

    【解决方案2】:

    你有一些事情搞混了..

    Motion 在您的基类中应该是虚拟的,以便它可以在子类中被覆盖。 您的子类需要使 PaintAt 覆盖而不是抽象。 基类需要将 Tick 实现为抽象方法。

    interface ICanvasTool
    {
        void Motion(Point newLocation);
        void Tick();
    }
    
    abstract class CanvasTool_BaseDraw : ICanvasTool
    {
        protected abstract void PaintAt(Point location);
    
        public virtual void Motion(Point newLocation)
        {
            // implementation
        }
    
        public abstract void Tick();
    }
    
    class CanvasTool_Spray : CanvasTool_BaseDraw
    {
        protected override void PaintAt(Point location)
        {
            // implementation
        }
    
        public override void Tick()
        {
            // implementation
        }
    }
    

    【讨论】:

    • 是的,前两个错误是不耐烦地为 SO 编写代码示例的结果。而且您的解决方案是正确的。谢谢。
    • 呃,等一下。为什么在 CanvasTool_BaseDraw 中 Motion 需要是虚拟的?我真的不需要允许子类覆盖它。
    • 我很抱歉。它没有必须。我只是假设你希望它是可覆盖的,因为它是一个基类。但是,使用“覆盖”是非法的,因为您正在实现接口,而不是继承抽象类或具有虚拟方法的类。
    【解决方案3】:

    另一种方法是不在基类声明中列出接口。如果每个派生类想要实现接口,则必须在其声明中列出 ICanvasTool,然后它单独负责实现接口的其余部分。我可以看到的一个缺点是您无法在基类中显式实现接口方法(即没有 ICanvasTool:Motion),但除此之外,这是一个开销相当低的版本。

    public interface ICanvasTool
    {
        void Motion(Point newLocation);
        void Tick();
    }
    
    public abstract class CanvasTool_BaseDraw
    {
        public void Motion(Point newLocation)
        {
            //some implementation
        }
    }
    
    public class CanvasTool_Spray : CanvasTool_BaseDraw, ICanvasTool
    {
        public void Tick()
        {
            //some implementation
        }
    }
    

    注意:我省略了 PaintAt,因为示例不需要它。

    【讨论】:

      【解决方案4】:

      如前所述,接口是一个契约,因此所有的接口都需要实现。如果消费者试图调用接口中定义但未在具体类中实现的内容,则应用程序将崩溃。

      【讨论】:

      • 是的,但是 CanvasTool_BaseDraw 不是一个具体的类。
      猜你喜欢
      • 1970-01-01
      • 2019-09-11
      • 2018-10-24
      • 2012-04-30
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 2020-02-04
      • 1970-01-01
      相关资源
      最近更新 更多