我正确使用接口吗?

时间:2013-11-12 14:22:14

标签: c# interface

使用界面的主要原因是使单元测试变得容易。但我觉得我不理解如何100%使用接口。

以下是我正在尝试做的简化版本:

public interface IPlan
{
    List<Plan> GetPlans(IPlan plan);
    List<Plan> GetAllPlans();
    List<string> DoSomethingElse();
}

public class Plan : IPlan
{
    List<Plan> GetPlans(IPlan plan)
    {
        // 
    List<Plan> planList = plan.GetAllPlans();

    //
    // Do stuff with planList...
    //
}

为了设置单元测试我需要能够模拟Plan类并从GetAllPlans返回一组计划,所以我看到我应该在这里使用接口,以便我可以正确地模拟它。我也理解(或者至少我认为)我应该将一个IPlan对象传递给GetPlans,然后我应该使用该IPlan对象来调用GetAllPlans ......但是这个设置似乎不对。

我是否错误地设置了这个?我传递的IPlan与它所在的类型相同(我会传递一个计划的IPlan)似乎很奇怪。对此有何建议?

4 个答案:

答案 0 :(得分:2)

我认为,你的混乱源于你的计划课的性质。你有一个类可能封装了一些计划数据,但它也提供了处理自身列表的方法。

在没有看到更多代码的情况下,很难确定,但您应该首先将GetPlansGetAllPlans移动到另一个处理计划列表的类中。然后将其签名更改为

是有意义的
List<IPlan> GetPlans();
List<IPlan> GetAllPlans();

甚至可能使该类具有通用性,约束于T : IPlan因此签名为:

List<T> GetPlans();
List<T> GetAllPlans();

答案 1 :(得分:0)

您正在正确实施它。接口中定义的每个方法都必须在具体类中实现。

我在你的问题中不明白的是......

“我传递的IPlan类型与它所在的类型相同似乎很奇怪(我将通过一个计划中的IPlan传递)。”

你可以澄清一下吗?

如果你的意思是List GetPlans(),那么这样的事情就完全没问题了。您计划返回一系列计划。

接口定义了每个实现的类应该实现的一些框架方法。这个基础是一个“契约”,以保证类将实现这个接口。这也意味着你可以做插件,你知道你有一个IPlugin接口,你可以使用say reflection来加载已经实现了这个接口的程序集,并开始在类中调用方法。

也许您需要一个名为Plan的实体类,然后将当前的Plan类重命名为Planlan或Planoperations。似乎这个类将完成工作,而您的计划只是一个可能获得设置者的实体/对象

答案 2 :(得分:0)

接口是合同,旨在(可能)应用于许多对象。它基本上告诉您的应用程序,实现接口的任何对象将实现您在接口中指定的方法。

它专为松耦合而设计。而不是接受Plan对象的方法,例如:

public bool DoSomething(Plan plan)
{
//....
}

你可以把它带到IPlan:

public bool DoSomething(IPlan plan)
{
//....
}

这意味着在运行时,您可以将任何内容传递给该方法,只要它实现IPlan。

这也意味着,对于单元测试,您可以创建一个IPlan的虚拟实现(例如,如果IPlan通常与数据库通信,您不希望它在您的测试中发生)并传递它 - 以便您只测试方法中的代码,而不是测试方法和它在Plan内部调用的任何内容。

答案 3 :(得分:0)

嗯,技术上你的实现是正确的,但是接口在其方法中使用该接口的具体实现似乎很奇怪。看起来IPlan试图“做太多”。

我会改为这样:

public interface IPlanRepository
{
    IEnumerable<IPlan> GetPlans(IPlan plan);
    IEnumerable<IPlan> GetAllPlans();
    IEnumerable<string> DoSomethingElse();
}

public class PlanRepository : IPlanRepository
{
    IEnumerable<IPlan> GetPlans(IPlan plan)
    {
        // fill a List with Plans
    }
    IEnumerable<IPlan> planList = GetAllPlans();
    {
        // fill a List with Plans
    }
    //
    // Do stuff with planList...
    //
}

public interface IPlan
{
   // properties and methods relating to a Plan (NOT how to "get" a Plan)
}

public class Plan : IPlan
{
    // implementation of properties and methods
}

请注意,我还将List返回类型更改为更通用的IEnumerable接口。这使您可以灵活地在实现中返回任何,如果您使用的话,会返回IEnumerable<Plan>,例如List<Plan>Plan[]IQueryable<Plan> ORM。