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

Как удовлетворить компилятор, когда только частично реализует интерфейс с абстрактным классом?

У меня есть интерфейс с именем IFish. Я хочу получить его с абстрактным классом (WalkingFishCommon), который обеспечивает неполную реализацию, так что классы, полученные из WalkingFishCommon, не должны реализовывать свойство CanWalk:

interface IFish
{
    bool Swim();
    bool CanWalk { get; }
}

abstract class WalkingFishCommon : IFish
{
    bool IFish.CanWalk { get { return true; } }

    // (1) Error: must declare a body, because it is not marked
    // abstract, extern, or partial
    // bool IFish.Swim();

    // (2) Error: the modifier 'abstract' is not valid for this item
    // abstract bool IFish.Swim();

    // (3): If no declaration is provided, compiler says 
    // "WalkingFishCommon does not implement member IFish.Swim()"
    // {no declaration}

    // (4) Error: the modifier 'virtual' is not valid for this item
    // virtual bool IFish.Swim();

    // (5) Compiles, but fails to force derived class to implement Swim()
    bool IFish.Swim() { return true; }
}

Я еще не обнаружил, как сделать компилятор счастливым, но все еще добивается цели принуждения классов, полученных от WalkingFishCommon, для реализации метода Swim(). Особенно непонятным является дельта между (1) и (2), где компилятор чередуется между жалобами на то, что Swim() не обозначен абстрактно, и в следующем дыхании жалуется, что он не может быть помечен как абстрактный. Интересная ошибка!

Любая помощь?

4b9b3361

Ответ 1

Просто объявите Swim как abstract и не пытайтесь использовать для него явное объявление интерфейса (т.е. удалить IFish).

abstract class WalkingFishCommon : IFish
{
    public bool CanWalk { get { return true; } }
    public abstract bool Swim();
}

Ответ 2

Как правило, интерфейсы реализуются неявно, определяя открытый член в классе для каждого члена интерфейса:

class MyFish : IFish
{
    public bool CanWalk { get { return ...; } }

    public bool Swim() { return ...; }
}

Если вы не хотите предоставлять реализацию для одного из этих членов, вы можете просто сделать его абстрактным:

abstract class FishBase : IFish
{
    public virtual bool CanWalk { get { return true; } }

    public abstract bool Swim();
}

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

abstract class FishBase : IFish
{
    public virtual bool CanWalk { get { return true; } }

    protected abstract bool Swim();

    bool IFish.Swim() { return Swim(); }
}

Ответ 3

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

abstract class WalkingFishCommon : IFish {
    public abstract bool CanWalk { get; }
    public abstract bool Swim();

}

Если явная реализация важна, вы можете решить эту проблему, введя защищенные абстрактные методы:

abstract class WalkingFishCommon : IFish {
    bool IFish.CanWalk { get { return CanWalkCore; } }
    bool IFish.Swim() { return SwimCore(); }

    protected abstract bool CanWalkCore { get; }
    protected abstract bool SwimCore();

}

Ответ 4

Не совсем решение, но, возможно, вы могли бы сделать что-то вроде

interface IWalkingFish
{
    bool CanWalk { get; }
}

interface ISwimmingFish
{
    bool Swim();
}

interface IFish : ISwimmingFish, IWalkingFish
{ }

abstract class WalkingFishCommon : IWalkingFish
{
    bool IWalkingFish.CanWalk { get { return true; } }
}

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