在课堂上没有直接实现的接口的实际用法是什么?

时间:2017-02-02 12:19:40

标签: c# oop

我想我在这里有一个非常幼稚的问题,我之前并不知道它甚至是可能的。如果我的标题问题有点模糊,请原谅我,因为我甚至不知道如何描述它。这段代码对我来说很奇怪。

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!"

我只想知道以下内容:

  • 描述这种方法的正确用语是什么?
  • 这种方法的实际好处是什么?
  • 它试图解决什么样的问题?或者什么情况适用?

4 个答案:

答案 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上被接受,而您只需要一个给定对象的完整类型的子集。