我定义了一个简单的界面
public interface IBla
{
public void DoThing();
public void DoAnotherThing();
public void Thing();
}
我有一堆实现此接口的类。然而,他们中的许多只需要该接口实现的三个函数中的两个,所以目前我也实现了其余的函数,并将它们留空:如下所示:
public void DoThing(){}
有更优雅的方式吗? 我 NOT 想要为此定义多个接口。 是否有类似“partialInterface”的东西,我不必将该接口的所有函数实现到实现该接口的类中?
由于
答案 0 :(得分:9)
实现接口时,实现接口的类型必须为所有提供接口详细信息的实现。
除了破坏界面外,不支持部分界面或类似于你想要的东西。
你基本上问“如何在不要求我提供+
运算符的情况下实现计算器界面”,简而言之,你不能。根据该界面,它将不再是计算器。
您最接近的是您可以创建一个基类,为整个接口或其中的一部分提供默认实现,并继承此基类型,以便继承的类变得更容易到使用较少的代码实现,但将提供整个界面。
答案 1 :(得分:2)
我知道你说你不想要单独的界面,但是为了将来希望正确回答这个问题的其他人的利益,这是:
您所描述的是将接口分离出来并使用接口继承的点。
public interface IBasic
{
void DoThing();
}
public interface IAdvanced : IBasic
{
void DoAnotherThing();
void Thing();
}
仅需要DoThing
的实施仅实施IBasic
。需要所有功能的实现实现IAdvanced
,其中包括来自IBasic
的方法以及其他功能。
答案 2 :(得分:0)
如果您的类没有实现所有方法,那么您可能需要将此接口分成更小的接口 许多特定接口比一个通用接口更好。
创建实现接口的类,抛出NotImplementedException
或者什么也不做,看起来像是SOLID规则违规。
答案 3 :(得分:0)
嗯,非常不鼓励只部分实现一个接口,有一种方法可以做到这一点。
大多数答案都谈到将界面分解为多个界面,这是有道理的。但是,如果这是不可能的,只需实现您不想以明确的方式使用的成员,如果它们被调用,您应该抛出NotSupportedException
。
如果您想查看正在使用的示例,请查看Microsoft自己的代码:http://referencesource.microsoft.com/#mscorlib/system/collections/objectmodel/readonlycollection.cs
void ICollection<T>.Add(T value)
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
}
答案 4 :(得分:0)
鉴于这些事情正在游戏循环中进行处理,可能是IBla
的实现类似于玩家角色,敌人,障碍物,导弹等等DoThing
等等Move
},Fire
等等。
如果是这样,那么你的方法是完全有效的。一个不动的对象应该有一个Move
方法(所以游戏循环可以调用它),并且因为它不能移动,所以一个空方法是一个有效的实现。
答案 5 :(得分:0)
如果您控制两个接口,则将接口分成多个接口。正如所建议的那样,一个接口可以从另一个接口继承,或者你可以让一些类实现这两个接口。
在这种情况下,接口继承可能是更好的选择,因为您不必修改已经实现更大接口的类。
如果较大的界面是您无法控制的界面,那么将其拆分为多个界面该怎么办?实现接口并留下一些没有实现的方法并不是一个好主意。如果一个类实现了一个接口,那么它应该真正实现该接口。
解决方案是定义您实际需要的较小接口,并创建一个类,使较大的接口适应较小的接口。
假设您有此界面
public interface IDoesFourThings
{
void DoThingOne();
void DoThingTwo();
void DoThingThree();
void DoThingFour();
}
你想要一个只实现其中两个的课程吗?如果班级真的只做两件事,你就不应该实施IDoesFourThings
。
首先,创建自己的界面:
public interface IDoesTwoThings
{
void DoThingA();
void DoThingB();
}
然后创建一个类,使IDoesFourThings
的实现适应您的界面。
public class DoesTwoThingsUsingClassThatDoesFourThings : IDoesTwoThings
{
private readonly IDoesFourThings _doesFourThings;
public DoesTwoThingsUsingClassThatDoesFourThings(IDoesFourThings doesFourThings)
{
_doesFourThings = doesFourThings;
}
public void DoThingA()
{
_doesFourThings.DoThingTwo();
}
public void DoThingB()
{
_doesFourThings.DoThingThree();
}
}
仅仅为了示例,我避免在IDoesTwoThings
中命名方法以匹配IDoesFourThings
中的方法。除非它们确实完全相同,否则新界面不需要与旧界面匹配。它是它自己的界面。该类通过使用IDoesFourThings
的内部实现来工作是隐藏的。
这与Interface Segregation Principle,我在SOLID中有关。考虑它的一种方法是:接口描述类的功能,但从客户端类的角度来看,它应该描述客户端需要什么。在这种情况下,客户需要两件事,而不是四件。
这种方法非常有用,因为它使我们能够一次处理一个类并推迟其他细节的实现。如果我们正在编写一个类,并且我们意识到它需要一个执行两件事的依赖,我们就可以为这两件事编写接口并让我们的类依赖它。 (现在该类更可测试,因为它依赖于我们可以模拟的接口。)然后,无论我们刚刚创建的那个新接口,我们还可以为它创建一个实现。
这是管理编写代码的复杂性并避免陷入困境的好方法,因为现在我们可以单独负责我们的一个班级,而不用太担心下一个班级和下一个班级将如何工作。 (我们可能知道它们将如何工作,但也许我们不会。无论哪种方式,它都不会减慢我们的速度。)