何时使用Interface类型的变量而不是具体类型

时间:2012-11-29 08:39:46

标签: c#

我有一个派生自Interface的类。现在该类必须实现Interfaces +中的所有方法,它还定义了另外两个方法。 现在我的问题是,这样做的好处/用例是什么:

IMyInterface varInt= new ConcreteImp();

以上,

ConcreteImp varInt= new ConcreteImp(); 

我看到这个模式在代码块中的每个位置使用,但不确定为什么使用它。

5 个答案:

答案 0 :(得分:2)

使用接口的好处在于减少部件对软件组件的具体实现的依赖性。在您发布的一行中,您将无法看到好处。可以从该界面的消费者中获益。

  

编辑:你会很read this article on abstractions

例如,假设您有一个接受类似Rent(IMovie)的接口的方法。另一个人将能够编写Rent()方法的实现,而不知道在调用方法时您将传递的IMovie类型的细节。然后,您将能够创建多个不同的IMovie实施方案,这些实施方案可能采用不同的结算方式,但Rent()方法无需处理此问题。

void Rent(IMovie movie)
{
    var price = movie.Price();
    movie.MarkReserved();
}

public interface IMovie { }

public class Oldie : IMovie
{
    private decimal _oldieRate = 0.8;

    public decimal Price()
    {
        return MainData.RentPrice * _oldieRate;
    }
    public decimal MarkReserved()
    {
        _oldiesDb.MarkReserved(this, true);
    }
}


public class Blockbuster : IMovie
{
    private decimal _blockbusterRate = 1.2;

    public decimal Price()
    {
        return MainData.RentPrice * _blockbusterRate ;
    }
    public decimal MarkReserved()
    {
        _regularDb.MarkReserved(this, true);
    }
}

这是接口有用的原因示例,但不是很好的代码设计示例。

根据经验,您应该编写方法,以便它们需要最少的输入才能工作,并且它们的输出提供了其他人在调用时使用的尽可能多的信息。例如,看一下以下签名:

public List<Entity> Filter(IEnumerable<Entity> baseCollection){ ... }

此方法仅请求IEnumerable<Entity>,因此它可以采用不同的集合类型,例如List<Entity>Entity[]或某些工具返回的自定义类型。但是你返回List<Entity>,这样你就不会将调用者限制为只有可枚举的元素。例如,她可以立即使用Linq返回值。

还有更多好处,例如在单元测试中,您可以在其中创建模拟对象,并告诉他们在与其余代码交互时如何表现。虽然,现在可以使用虚拟方法对类进行此操作。

答案 1 :(得分:1)

假设您希望代码中的其他位置能够将IMyInterface的不同实现分配给varInt变量。然后需要使用类型IMyInterface声明该变量。

或者,如果您想向任何代码读者明确表示您打算使用varInt定义的所有接口都使用IMyInterface定义的接口,那么类型声明就会明确说明。

答案 2 :(得分:1)

当您需要在派生类使用界面中强制执行功能时。

当你需要将数据从超类传递给子类时,你就使用了具体的类。它是接口和子类背后的基本oop理念。

答案 3 :(得分:0)

在你的具体例子中,我会说它并不重要,因为你使用new并创建一个具体的类型。当您开始使用dependency injection时,它开始变得更有用。

更有用的场景如下所示:

public SomeResultType DoSomething(ISomeType obj)
{
    //to something with obj
    // return someResultType
}

只要它实现ISomeType,就可以使用任何类型调用上述内容。但是在使用new关键字的示例中,我会使用var。您仍然可以将其视为它实现的类型,因为它继承了该类型。

答案 4 :(得分:0)

假设IMyInterface有“Draw”方法,现在所有派生类都必须实现“Draw”方法。如果你有一个“引擎”类,其方法是“渲染(IMyInterface形状)”,你只需调用“绘图”方法,无论形状如何。每个形状都按照自己的意愿画画。 你可以看看设计模式,你可以看到界面的魔力;)