继承接口方法的重新实现

4

我还不太了解如何使用接口,所以需要请教一下 :-)

我使用一个BaseClass类,它实现了IBaseClass接口。这个接口只包含一个声明:

public interface IBaseClass
{
    void Refresh ();
}

所以我在我的基类中实现了一个刷新方法:

    public void Refresh ()
    {
        Console.WriteLine("Refresh");
    }

现在我想使用一些继承自这些Baseclass并实现了IBaseClass接口的类:

    public class ChildClass : BaseClass,IBaseClass
    {
    }

但因为我在我的BaseClass中实现了“刷新”,所以我不必再次实现该方法。我应该怎么做,才能强制将“刷新”方法的实现推广到所有BaseClass的子类以及childclass的所有子类。

谢谢 kooki


为什么您取消了我的答案?您找到更好的信息了吗?如果是这样,请发布并接受您自己的回复,以便将问题标记为已解决。 - Levi Botelho
6个回答

4
您不能强制派生类按照您指定的方式重新实现该方法。您有三个选项:
  1. 不要在基类中定义refresh。接口将强制子类实现它。
  2. 如果接口的唯一目的是强制实施,则放弃接口,并将基类声明为abstract,以及refresh,对于此情况下您不会给出一个实现。
  3. 在基类中定义refreshvirtual。这允许重写但不会强制执行。这就是ToString()的工作原理。
这一切都假设您的基类比单个方法更大。如果您的代码确实与您发布的代码完全相同,则Oded的答案是最佳选择。

3
简单来说,不提供基类实现,你就必须在每个继承类中实现该方法。
一种实现方式是将 BaseClass 声明为 抽象类
public abstract BaseClass : IBaseClass
{
    public abstract void Refresh();
}

但是我也需要在基类中实现。但如果没有其他可能性,我将实现一个名为“BaseRefresh”的新方法,并且子类可以在接口实现上调用它。 - Kooki
@Kooki - 为什么你还需要在BaseClass中实现呢? - Oded
因为有一些字段需要在BaseClass中使用这些“Refresh”进行设置。 - Kooki
上面的代码完全复制了IBaseClass,虽然你可以这样做,但为什么要这样呢? - PeteH
准确地说,抽象是解决方案,派生类中接口的重新实现可能会很微妙:http://blogs.msdn.com/b/ericlippert/archive/2011/12/08/so-many-interfaces-part-two.aspx - AlexH
@PeteH - 这就是我所提出的问题,OP的评论表明基类需要用于其他共享数据。 - Oded

3
我应该怎么做,才能强制实现“刷新”到BaseClass的所有子类以及childclass的所有子类中。

像这样:

interface IBase
{
    void Refresh();
}

abstract class BaseClass : IBase
{
    public abstract void Refresh();
}

class ChildClass : BaseClass
{
    public override void Refresh()
    {
        // Your code
    }
}

你甚至可以省略接口(我的经验法则是:如果一个接口只被一个类实现,就抛弃这个接口。不要固守于接口病。一个抽象类很好地代表了一个接口,也可以参考Interface vs Abstract Class (general OO))。
如果你需要在基类中实现,就按照以下方式构建:
(abstract) class BaseClass ( : IBase)
{
    public virtual void Refresh()
    {
        // Your code
    }
}

然后,您可以从派生类中调用它:

public override void Refresh()
{
    // Your code

    // optionally, to call the base implementation:
    base.Refresh();
}

1
让我们逐步来看看这个。 1:您有一个接口,它定义了您的代码合同,如下所示:
public interface IBase
{
    void Refresh();
}

2:您有一个实现接口的基类。(您会注意到刷新的实现是虚拟的。这允许您在派生类中重写此方法)。

class Base : IBase
{
    public virtual void Refresh()
    {
        //Implementation
    }
}

3:您有一个超类,它派生自基类。(您会注意到派生类不需要显式实现IBase,因为它已经在更低的级别上完成了。我将向您展示如何测试其完整性)。

class Child : Base
{
    public override void Refresh()
    {
        base.Refresh(); //You can call this here if you need to perform the super objects Refresh() before yor own.
        //Add your implementation here.
    }
}

此时你可能会想:“好吧,那么Child是如何实现IBase的呢?”答案是通过Base间接实现,因为Child继承了Base,所以它也获得了IBase的实现。
因此,如果你写下以下代码:
IBase instance = new Child();

这是完全合法的,因为实质上,Child 是间接继承自 IBase
如果您想测试这个,可以在您的代码中这样做:
bool canAssign = typeof(IBase).IsAssignableFrom(typeof(Child));
//canAssign should be true as Child can be assigned from IBase.

1
如果您想提供一个默认实现,可以在基类中将其标记为虚拟的,这样如果需要,子类就可以覆盖该实现。
否则,在基类中将该方法标记为抽象的,这样就强制子类自己实现该方法。

0

也许使用关键字可以帮助您解决这个问题;

namespace ConsoleApplication1
{
    interface IBase
    {
        void Referesh();
    }
    public class Base1 : IBase
    {
        public void Referesh()
        {
            Console.WriteLine("Hi"); 
        }
    }
    public class Class1 : Base1, IBase
    {
        public new void Referesh()
        {
            Console.WriteLine("Bye");
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            Class1 obj = new Class1();
            obj.Referesh();

            Console.ReadKey();
        }
    }
}

如果 Base1 明确期望子类能够实现自己的 Refresh 版本,则 Base1 应将该方法定义为 virtual - comecme
这并不是一个理想的解决方案,因为 new 关键字意味着方法隐藏。new 关键字应该用于定义新的方法/属性实现,而原始方法不是虚拟的(无法覆盖)。当您设计类并且知道该方法将被覆盖时,请将该方法设置为虚拟方法。 - Matthew Layton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接