【问题标题】:Explicitly implementing an interface with an abstract method使用抽象方法显式实现接口
【发布时间】:2011-05-01 23:34:27
【问题描述】:

这是我的界面:

public interface MyInterface {
    bool Foo();
}

这是我的抽象类:

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

这是编译器错误: “修饰符'abstract'对此项无效。

我应该如何继续使用抽象方法显式实现抽象?

【问题讨论】:

    标签: c# interface abstract


    【解决方案1】:

    我不知道你为什么需要。为什么不让抽象类的具体实现从接口实现成员呢?真的是一回事。

    【讨论】:

    • 你的意思是这样?公共接口 MyInterface { bool Foo(); } public abstract class MyAbstractClass : MyInterface { } public class ConcreteClass : MyAbstractClass { } 问题是 MyAbstractClass 应该从 MyInterface() 实现 Foo()。
    • 我不确定您所说的“MyAbstractClass 应该从 MyInterface() 实现 Foo()”是什么意思。在您的示例中,您希望 Foo() 是抽象的,因此您没有实现它。如果 ConcreteClass 不提供 Foo() 的实现,则不会编译。
    【解决方案2】:

    abstract method 没有实现,因此不能用于显式实现接口方法。

    【讨论】:

    • 感谢您陈述显而易见的事实,同时也表明我对某些 C# 语法一无所知。
    【解决方案3】:

    你不能,基本上。反正不是直接的。您不能重写显式实现接口的方法,并且您必须重写抽象方法。您最接近的可能是:

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

    这仍然显式地实现接口并且强制派生类实际提供实现。这些是您想要实现的方面吗?

    【讨论】:

    • 是的。我想强制从 MyAbstractClass 继承的类实现 Foo(),但同时我希望 MyAbstractClass 显式实现 MyInterface.Foo()。现在这就是我在我的代码中所做的。
    • 虽然这是 - 我相信 - 唯一的 direct 解决方案,但它的缺点是需要声明相同的方法 3 次 - 显式接口实现,然后是受保护的抽象方法,最后是派生类中的实现。我很好奇,为什么不能直接做——既然 MyAbstractClass 是抽象的,接口所需的方法可能会被视为该类的抽象方法,确保它们在某些派生类中实现。
    【解决方案4】:

    您必须使用接口成员的隐式实现而不是显式实现:

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

    【讨论】:

    • 我明白了。这是一个非常直接的点。太糟糕了,我没有更多的赞成票了。
    【解决方案5】:

    我能做到

    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();
        }
    }
    

    【讨论】:

    【解决方案6】:

    除了 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();
    

    【讨论】:

      【解决方案7】:

      抽象一个抽象类中实现的所有接口方法,即使你不使用它们。

      这种特殊情况要求您使用一个接口实现 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
      }
      

      【讨论】:

        【解决方案8】:

        事实上,除了使用抽象辅助方法之外,还有另一种选择,它仍然保持实现私有:

        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# 中可能没有不完整的接口实现。)

        优点是节省了一条可能导致 CPU 流水线停顿的 calli 指令。但是,影响很小,因为由于接口调用,无论如何都无法内联该方法。所以我只推荐它用于性能关键的情况。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-22
          • 2011-11-20
          • 1970-01-01
          • 2020-02-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-17
          相关资源
          最近更新 更多