Подтвердить что ты не робот

Явно реализую интерфейс с абстрактным методом

Вот мой интерфейс:

public interface MyInterface {
    bool Foo();
}

Вот мой абстрактный класс:

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

Это ошибка компилятора: "Модификатор" abstract "недействителен для этого элемента.

Как я могу продолжать прямое использование абстрактного абстрактного метода?

4b9b3361

Ответ 1

Вы не можете, в принципе. Во всяком случае, это не так. Вы не можете переопределить метод, который явно реализует интерфейс, и вы должны переопределить абстрактный метод. Ближе всего вы могли бы прийти:

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

protected abstract bool FooImpl();

Это все еще реализует интерфейс явно и заставляет производные классы фактически обеспечивать реализацию. Это те аспекты, которые вы пытаетесь достичь?

Ответ 2

Вы должны использовать неявную реализацию члена интерфейса вместо явной реализации:

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

Ответ 3

Я не уверен, зачем вам это нужно. Почему бы не позволить конкретной реализации абстрактного класса реализовать элемент из интерфейса? Это тоже самое.

Ответ 4

абстрактный метод не имеет реализации, поэтому он не может использоваться для явного внедрения метода интерфейса.

Ответ 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

В дополнение к объяснению Джона: это способ обойти проблему, а не решать ее напрямую и работать только в определенных обстоятельствах, но, возможно, кто-то выиграет от этой идеи.

Если вы планируете передавать все вызовы метода интерфейса (или на большинстве) в производный класс, вы можете сделать это следующим образом:

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

Вывести все методы интерфейса, которые реализованы в абстрактном классе, даже если вы их не используете.

В этом конкретном случае требуется, чтобы вы реализовали иерархию из двух или более абстрактных классов с интерфейсом.

Я также пытался реализовать иерархию на С#. Мне нужен интерфейс, но мне нужен класс Abstract, потому что большинство свойств для интерфейса одинаковы. Для этого мне пришлось создать отдельный абстрактный класс с реализацией, а затем мои классы Concrete или, в моем случае, еще один абстрактный класс, наследовали интерфейс и абстрактный класс.

Я не думаю, что этот первый пример является хорошим примером по многим причинам, но я должен был его получить, потому что компилятор не разрешил 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

Фактически существует еще один вариант, чем использование абстрактного вспомогательного метода, который по-прежнему сохраняет реализацию private:

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, поэтому компилятор не может гарантировать, что метод действительно переопределен. (Жаль, что абстрактные классы могут не иметь неполных реализаций интерфейса в С#.)

Преимущество заключается в том, что вы сохраняете одну инструкцию calli, которая, вероятно, вызовет проблемы с конвейерами CPU. Тем не менее, влияние довольно малое, поскольку метод не может быть встроен в любом случае из-за вызова интерфейса. Поэтому я бы рекомендовал его только для критически важных случаев.