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