Явная реализация интерфейса с абстрактным методом - PullRequest
14 голосов
/ 28 октября 2010

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

public interface MyInterface {
    bool Foo();
}

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

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

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

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

Ответы [ 8 ]

21 голосов
/ 28 октября 2010

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

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

protected abstract bool FooImpl();

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

13 голосов
/ 28 октября 2010

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

public abstract class MyAbstractClass : MyInterface
{
    public abstract bool Foo();
}
1 голос
/ 28 октября 2010

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

1 голос
/ 28 октября 2010

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

0 голосов
/ 26 апреля 2016

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

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

0 голосов
/ 06 января 2016

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

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

Я также пытался реализовать иерархию в C #.Мне нужен интерфейс, но я хотел абстрактный класс, потому что большинство свойств одинаковы для интерфейса.Для этого мне нужно было создать отдельный класс 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
}
0 голосов
/ 19 марта 2014

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

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

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 голосов
/ 21 октября 2012

Я могу сделать это

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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...