Явно реализую интерфейс с абстрактным методом
Вот мой интерфейс:
public interface MyInterface {
bool Foo();
}
Вот мой абстрактный класс:
public abstract class MyAbstractClass : MyInterface {
abstract bool MyInterface.Foo();
}
Это ошибка компилятора:
"Модификатор" abstract "недействителен для этого элемента.
Как я могу продолжать прямое использование абстрактного абстрактного метода?
Ответы
Ответ 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. Тем не менее, влияние довольно малое, поскольку метод не может быть встроен в любом случае из-за вызова интерфейса. Поэтому я бы рекомендовал его только для критически важных случаев.