是否建议将接口作为返回类型?

时间:2010-06-14 01:59:34

标签: c# interface return-type

我有一组具有相同功能但具有不同逻辑的类。但是,每个类函数都可以返回许多对象。将返回类型设置为接口是安全的吗?

每个类(都使用相同的接口)使用不同的业务逻辑来执行此操作。

protected IMessage validateReturnType; <-- This is in an abstract class

public bool IsValid() <-- This is in an abstract class
{
    return (validateReturnType.GetType() == typeof(Success));
}

public IMessage Validate()
{
    if (name.Length < 5)
    {
        validateReturnType = new Error("Name must be 5 characters or greater.");
    }
    else
    {
        validateReturnType = new Success("Name is valid.");
    }

    return validateReturnType;
}

单元测试功能的返回类型是否存在任何缺陷?另外,为了让它们成功运行需要运行的功能,它被认为是不好的设计吗?在此示例中,必须在IsValid()之前运行Validate(),否则IsValid()将始终返回false。

谢谢。

4 个答案:

答案 0 :(得分:10)

  

但是,每个类功能都可以   返回一些对象。这很安全   将返回类型设置为   接口

这是一种很好的做法并且很常见。例如,看看COM的构建方式,它很大程度上依赖于这种方法。

  

单元测试函数的返回类型是否存在任何缺陷

没有

  

另外,为了让它们成功,需要运行功能被认为是不好的设计吗?在此示例中,必须在IsValid()之前运行Validate(),否则IsValid()将始终返回false。

这对于使用面向对象的编程范例来说很好,例如使用套接字。在发送和接收数据之前,通常会有一个connect方法。

据说,保持较少的状态比通常更多的状态更好,因为以这种方式更容易证明你的程序是正确的。例如,您必须以一种方式测试依赖于此函数的每个函数,而不是现在以两种方式。如果您有很多州,可能的计划状态会呈指数级增长。如果您对州为何是一件坏事感兴趣,请查看functional programming

答案 1 :(得分:4)

  

另外,为了让它们成功,需要运行功能被认为是不好的设计吗?在此示例中,必须在IsValid()之前运行Validate(),否则IsValid()将始终返回false。

有一些例外,但一般来说,你应该避免构建这种API。这被称为“时间依赖”,这只是“一件事需要在另一件事之前发生”的一个奇特用语。时间依赖性的问题在于它们很少是自我描述的。换句话说,API本身不会如何使用它。依赖于时间依赖性的API通常比类似的代码更难以直观地理解和使用。

在您的示例中,我考虑使用以下设计目标重构API:

  1. 摆脱IsValid altogther。
  2. 验证返回验证错误列表。
  3. 重新定义“success”,因为Validate()返回一个没有错误的空列表。
  4. 如果您必须拥有IsValid,请重新定义它以检查#3。如果要缓存结果以便不必经常重新计算IsValid,请考虑实现INotifyPropertyChanged并使PropertyChanged上的缓存结果无效。

答案 2 :(得分:1)

将接口作为返回类型是好的,因为您的方法将与更多类型的消息兼容。

答案 3 :(得分:1)

返回接口通常很好,因为它隐藏了实现。 (当然,你不应该隐藏超过必要的......)

在你的例子的情况下,我有点担心你想要对你的函数的实际返回类型进行单元测试,而使用接口的点就是隐藏它。看起来您的实际代码将依赖于实际的返回类型,而 会闻起来很糟糕。

我最好向IsValid()添加一个抽象方法IMessage,在SuccessError中覆盖它,然后直接调用validateReturnType.IsValid()。对我来说听起来更多OO。 OO和虚拟方法的目标是避免基于类型的案例切换,就像您在IsValid()中所做的那样。