明确实现带有抽象方法的接口

16

这是我的接口:

public interface MyInterface {
    bool Foo();
}

这是我的抽象类:

public abstract class MyAbstractClass : MyInterface {
    abstract bool MyInterface.Foo();
}

这是编译错误信息:"The modifier 'abstract' is not valid for this item."

我应该如何明确实现一个抽象方法并使其为抽象的?

8个回答

25

基本上你不能这样做。至少不能直接这样做。你不能覆盖实现接口的方法,而你需要覆盖抽象方法。最接近的解决方案可能是:

bool MyInterface.Foo() {
    return FooImpl();
}

protected abstract bool FooImpl();

那仍然显式实现了接口并迫使派生类实际提供实现。这些是您试图实现的方面吗?


1
是的。我想强制继承自MyAbstractClass的类实现Foo(),但同时我希望MyAbstractClass明确实现MyInterface.Foo()。目前这就是我在我的代码中正在做的。 - acermate433s
1
尽管我认为这是唯一的直接解决方案,但它有一个缺点,需要声明相同的方法三次 - 显式接口实现,然后是受保护的抽象方法,最后在派生类中实现。我很好奇,为什么不能直接完成 - 现在MyAbstractClass是抽象的,接口所需的方法可以被视为该类的抽象方法,在某个派生类中确保它们的实现。 - Spook

21

你需要使用隐式实现接口成员而不是显式实现:

public abstract class MyAbstractClass : MyInterface
{
    public abstract bool Foo();
}

2
我明白了。这更加直接简洁。可惜我没有更多的赞了。 - acermate433s

2
事实上,除了使用抽象的帮助方法之外,还有另一种选择可以保持实现私有:
public abstract class MyAbstractClass : MyInterface
{
  bool MyInterface.Foo() // must be overridden
  { throw NotImplementedException(); // never called
  }
}

public class MyDerivedClass : MyAbstractClass, MyInterface
{
  bool MyInterface.Foo() // overrides MyInterface.Foo
  { // Place your implementation here
  }
}

如果接口有很多方法,只有一部分在派生类中被重新定义,那么这种模式也可以使用。当然,您也可以将其用于覆盖普通私有接口实现。

主要缺点是Foo不能在MyAbstractClass中声明为抽象类,因此编译器无法确保该方法是否被覆盖。 (C#不允许抽象类具有不完整的接口实现,这真是可惜。)

优点是您可以节省一个calli指令,从而避免CPU流水线停顿。但是,由于接口调用,该方法无法进行内联,因此影响相对较小。因此,我建议仅在对性能至关重要的情况下使用它。


2

抽象方法没有实现,因此不能用于显式地实现接口方法。


3
感谢你指出显而易见的问题,同时也明显地表达了我对某些C#语法的无知。 - acermate433s

1

我不确定你为什么需要这样做。为什么不让抽象类的具体实现实现接口成员呢?其实这是一样的。


1
你的意思是这样吗?public interface MyInterface { bool Foo(); }public abstract class MyAbstractClass : MyInterface { }public class ConcreteClass : MyAbstractClass { }问题在于MyAbstractClass应该实现来自MyInterface的Foo()。 - acermate433s
我不确定你所说的“MyAbstractClass应该从MyInterface实现Foo()”是什么意思。在你的示例中,你想要Foo()是抽象的,所以你没有实现它。如果ConcreteClass没有提供对Foo()的实现,它将无法编译。 - Phill

0

即使您不使用它们,也要将在抽象类中实现的所有接口方法抽象化。

这种情况需要您实现具有接口的2个或多个抽象类层次结构。

我也尝试在C#中实现层次结构。我需要一个接口,但我想要一个抽象类,因为大多数属性对于接口来说是相同的。为此,我必须创建一个单独的带有实现的抽象类,然后我的具体类,或者在我的情况下是另一个抽象类,将继承接口和抽象类。

我认为这第一个例子出于许多原因都不是一个好的例子,但我必须拥有它,因为编译器不允许FooBar实现Foo,然后再有另一个抽象类继承FooBar。所以我有一个带有抽象方法bar()的抽象类,和带有bar()方法的接口。

public interface Foo { 
    bool bar();
    //other stuffs
}


public abstract class FooBar {
    public abstract bool bar();
    //Other stuffs
}

public abstract class FooBarAbstraction: FooBar, Foo {
     //other stuffs
     //Don't supply the interface and abstract here
}

public class FooBarConcrete: FooBarAbstraction {
    public override bool bar() {
        return true;
    }
   //other stuffs
}

这是我的第一次尝试,然后我变得好奇并开始思考。我找到了这个解决方案。更好的解决方案。

public interface Foo { 
    bool bar();
    bool buzz();
    //other stuffs
}


public abstract class FooBar : Foo{
    public abstract bool bar();
    public abstract bool buzz();
    //Other stuffs
}

public abstract class FooBarAbstraction: FooBar {
     //other stuffs
     //Don't supply the interface and abstract here
     // override everything else
     public override bool buzz() {
         return false;
     }
}

public class FooBarConcrete: FooBarAbstraction {
    public override bool bar() {
        return true;
    }
   //other stuffs
}

0
除了Jon的解释之外:这是绕过问题而不是直接解决问题的一种方式,只在特定情况下起作用,但也许有人会从这个想法中受益。
如果你计划将所有(或者至少大多数)接口方法调用传递到派生类中,可以按照以下方式实现:
public interface MyInterface 
{
    bool Foo();
}

public abstract class MyAbstractClass
{
    public abstract MyInterface AsMyInterface();
}

public class MyDerivedClass : MyInterface
{
    public override MyInterface AsMyInterface()
    {
        return this;
    }

    public bool Foo()
    {
        return false;
    }
}

...

MyAbstractClass c = new MyDerivedClass();
MyInterface i = c.AsMyInterface();
bool b = i.Foo();

0

我能够做到这一点

public interface SampleInterface
{
    void member1();
    void member2();
    void member3();
}

public abstract class Client2 : SampleInterface.SampleInterface
{
    public void member1()
    {
        throw new NotImplementedException();
    }

    public abstract void member2();


    public void member3()
    {
        throw new NotImplementedException();
    }
}

public class Client3 : Client2
{
    public Client3()
    {

    }

    public override void member2()
    {
        throw new NotImplementedException();
    }
}

3
你正在隐式地实现这个接口,而不是显式地实现。请阅读有关差异的内容:http://blogs.msdn.com/b/mhop/archive/2006/12/12/implicit-and-explicit-interface-implementations.aspx - Piotr Sobiegraj

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