C# 当仅部分实现带有抽象类的接口时,如何满足编译器的要求?

C# 当仅部分实现带有抽象类的接口时,如何满足编译器的要求?,c#,abstract-class,C#,Abstract Class,我在这里有一个名为IFish的界面。我想用一个抽象类(WalkingFishCommon)来派生它,它提供了一个不完整的实现,这样从WalkingFishCommon派生的类就不必实现CanWalk属性: interface IFish { bool Swim(); bool CanWalk { get; } } abstract class WalkingFishCommon : IFish { bool IFish.CanWalk { get { return tr

我在这里有一个名为
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()
没有标记为抽象,然后又抱怨它不能标记为抽象。有趣的错误


有什么帮助吗?

只需将
Swim
声明为
abstract
,不要尝试对其使用显式接口声明(即删除
IFish


通常,通过在类中为接口的每个成员定义公共成员来隐式实现接口:

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

如果您真的不需要显式实现接口,您可以简单地执行以下操作:

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

}

这不完全是一个解决方案,但也许你可以这样做

interface IWalkingFish
{
    bool CanWalk { get; }
}

interface ISwimmingFish
{
    bool Swim();
}

interface IFish : ISwimmingFish, IWalkingFish
{ }

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

然后,您可以为抽象类和具体类使用不同的接口。

您可以在IFish.Swim中抛出NotImplementedException,尽管它不是您真正想要的,但您必须实现所有接口。你可以声明一个空方法而不使用它。好吧,如果这只是语言语义的一个限制,我可以接受。也许我误读了那些似乎暗示这是可能的消息来源……
public abstract bool Swim()
可以工作,但似乎您希望显式实现接口…@Stabledog:您正在显式实现接口(没有
public
方法,而是
IFish.
prefix)。这意味着,除非先将实例强制转换为
IFish
,否则无法对这些鱼的实例调用它们。如果没有显式实现,那么可以对实现接口的任何类型调用该方法。见挑剔:这不太一样:现在你可以做
((WalkingFishCommon)new SomeFish()).Swim()
@ThomasLevesque,如果他做了,我会再看一遍。我认为他可能不需要显式接口实现,显然,试图允许显式接口实现会使问题变得非常复杂。我只是遇到了一个误解——我认为需要在派生方法声明中指定接口名称,或者最终得到一个同名的不相关方法。所以这个答案澄清并解决了这个问题。Thanks@Stabledog如果接口方法是显式实现的,则只能通过接口类型的标识符调用该方法;如果没有显式实现接口的类的实例,则必须将其类型转换为接口,然后才能调用这些方法。根据我的经验,人们很少使用显式实现,除非他们需要。请参阅:@Stabledog它也很有用,因为如果您有不同的接口,所有接口都带有
Count
Length
Size
等方法,那么您不会让所有三个成员都将intellisense弄乱;您可以显式地实现一个,隐式地实现另外三个,以便提供功能,但不要混淆试图确定
Count
Length
是否实际上是同一件事的用户。
protected
方法不会隐式地实现接口,只有一个
public
方法将被删除。最上面的代码将不满足IFish接口,也不满足compile@JeanHominal,这是怎么一个问题?受保护的方法不是接口的实现,它们甚至没有与接口中相同的名称……我说的是您的第一个示例,而不是第二个。@Stabledog,是的,完全正确。您通过为接口成员提供实现来满足编译器的要求,并且仍然强制派生类实现抽象方法。
interface IWalkingFish
{
    bool CanWalk { get; }
}

interface ISwimmingFish
{
    bool Swim();
}

interface IFish : ISwimmingFish, IWalkingFish
{ }

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