我想我在这里有一个非常幼稚的问题,我之前并不知道它甚至是可能的。如果我的标题问题有点模糊,请原谅我,因为我甚至不知道如何描述它。这段代码对我来说很奇怪。
public interface IMyInterface
{
void ImplementMe();
}
public class StandAlone
{
public void ImplementMe()
{
Console.writeline("It works!");
}
}
public class SubClass : StandAlone, IMyInterface
{
// no need to implement IMyInterface here but it still work!!!
}
IMyInterface myInterface = new SubClass();
myInterface.ImplementMe(); // Output : "It works!"
我只想知道以下内容:
答案 0 :(得分:6)
好吧,我想到的第一个案例 - 当你不拥有StandAlone
类的源代码时,后来你决定引入描述StandAlone
类行为的界面。例如。用于单元测试(这不是模拟您不拥有的代码的最佳实践,但有时可能有用)或者您希望在某些情况下提供StandAlone
行为的替代实现。所以要么你没有选择对这些代码进行单元测试:
public class SUT
{
private readonly StandAlone dependency;
public SUT(StandAlone dependency)
{
this.dependency = dependency;
}
// ...
}
但是,如果您要介绍界面,您实际上可以从IMyInterface
而不是StandAlone
切换到依赖关系。并提供SubClass
作为零接口的实现。
public class SUT
{
private readonly IMyInterface dependency;
public SUT(IMyInterface dependency)
{
this.dependency = dependency;
}
// ...
}
答案 1 :(得分:3)
但是SubClass
确实实现了IMyInterface
- 它拥有所有必需的公共成员以及正确的签名。没有具体的术语,因为没有什么奇怪的。
事实上,有些语言更进一步,并允许您将任何对象转换为接口,只要该类具有正确的成员(并且在更灵活的语言中,即使它没有。)
主要的好处是与使用接口的任何其他方式相同 - 它允许您从接口抽象实现。它只是一个必须进行显式接口实现的快捷方式,如:
class SubClass : BaseClass, IInterface
{
void IInterface.MyMethod()
{
base.MyMethod();
}
}
您可能认为您可以在基类中实现该接口,但有很多原因可以解释为什么:
BaseClass
。如果你尝试,你可能会发现更多的理由。
但重点是:为什么不呢?您需要 reason 来做某事(扩展基类的定义而不仅仅是子类)。在代码库中随处添加抽象很少有用 - 您试图在明确意图和实现清晰度之间找到一个很好的平衡点。基类上的接口可能有助于或阻碍它。
答案 2 :(得分:2)
这种模式的一个合法用法(仅仅是原始程序员应该将接口放在基类上)可能是Standalone
在第三方(或不可访问)程序集中,{{1}用自己的代码编写,以提供Facade。
考虑一下;
IMyInterface
定义接口。ImplementMe
位于ThirdParty.dll中并提供了这个确切的方法名称(可能是您故意在该方法名称上建模您的界面)Standalone
以实现您的功能。 Standalone
的方法,你的onw类实现了你自己的接口。 (ImplementMe
)然后,您可以使用DI来实例化public class MyOwnImplemetation : IMyInterface {... }
或StandAlone
的正确实现,但将它们视为MyOwnImplemetation
。
答案 3 :(得分:0)
并非所有类都是接口的直接实现。
例如,让我们根据简单的类继承放置一个好的示例:
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public string LastName { get; set; }
}
public class Employee : Person
{
}
现在,让我们想象一下,我们需要在一些常见的商店中存储唯一可识别的对象,我们不关心实体的类型,而只关注它们是唯一可识别的。
顺便说一下,我们认为人不应该存储在这样的商店中,因为它们不是我们组织内的有效实体,但它们只是为了提高代码的可重用性而且 don不要重复自己。所以我们定义一个这样的界面:
public interface ICanBeUniquelyIdentifiable
{
Guid Id { get; set; }
}
...我们不会在Person
上实施,但我们会在Employee
上执行此操作:
// Now an employee is an actual object that can be uniquely identifiable,
// and this isn't true because Person has an Id property, but because
// Employee fulfills the contract!
public class Employee : Person, ICanBeUniquelyIdentifiable
{
}
我想说你的推理应该是你实现了真正重要的接口,并且可重用性不应该是实现接口时的关键点。
实际上,您应该在对象上实现接口,这些接口应该在某些API上被接受,而您只需要一个给定对象的完整类型的子集。