2

Some time ago I've read something like a 'convention' for OOP, but I'm not sure if I remember it correctly.

It says that a method must take the most generic objects in inheritance hierarchy as parameters, while return the most descendant ones.

Is this true and if it is, can anybody explain a lil bit?

Example:

IList<T> someMethod(IList<T> someList)
{
    IList<T> resultList = new List<T>();

    ... do something with resultList ...

    return resultList;
}

According to the 'convention' the method above should return List, instead of IList?

4

5 回答 5

5

通常情况下,一个类声明一个指向对象的泛型指针。通常是基类。在运行时,通过构造函数或 setter 方法注入一个更具体的类,该方法允许在不修改代码的情况下扩展代码。这是软件工程中的圣杯。有一条规则说基类应该可以被它们的派生类替换——里氏替换原则。我不确定您的示例似乎没有使用 someList 参数。

于 2013-08-08T11:31:58.573 回答
3

尝试阅读有关Liskov Substitution Principle的内容,特别是有关返回类型的协方差

遵循上述原则,您将返回IList而不是List

...
Liskov 的原则对新的面向对象编程语言中采用的签名提出了一些标准要求(通常在类级别而不是类型级别;请参阅名义与结构子类型的区别):

  • 子类型中方法参数的逆变。
  • 子类型中返回类型的协方差。
  • 子类型的方法不应抛出新的异常,除非这些异常本身是超类型方法抛出的异常的子类型。
于 2013-08-08T11:33:26.957 回答
2

我认为您指的是稳健性原则,也就是 Postel 定律。你可以用谷歌搜索它并找到大量信息。

于 2013-08-08T11:33:13.723 回答
1

是的,它通常应该返回 List,因为 List 可以隐式转换为 IList。

该约定旨在简化用户代码并使方法尽可能通用。如果在您的示例中,您使用了一个List<T>参数,则该方法将很难调用,如果用户使用的是自定义IList实现,List即使它提供了相同的功能,并且实际上对您没有任何影响方法。

同样,如果您的方法返回 aIList而不是 a List,则任何在 中定义List但不在 in 中定义的方法都IList将无法访问(除非您知道它IList实际上是 aList并执行强制转换)。虽然,这是一个比前一个更弱的规则。

考虑以下情况:您实现了返回 a 的方法List,但随后您意识到还有另一个OtherCollection : IList更适合并提供更好性能的类。现在,您必须修改函数的返回类型,新版本将与旧版本不兼容,因为您更改了公共方法的返回类型。

因此,虽然这对于方法参数几乎总是正确的,但在返回类型方面它变得更加复杂。在处理争论时,你应该问自己:

  1. 我真的需要这么特殊的类型吗?
  2. 我将来需要这种特定类型的可能性有多大?

在处理返回类型时,另一方面:

  1. 方法用户真的需要这种特定类型吗?
  2. 用户是否需要显式转换才能访问我的返回值的有用方法?
  3. 我将来需要更通用的返回类型的可能性有多大?
于 2013-08-08T11:41:28.573 回答
1

以前从来没有这样听过,但它是有道理的。我们先来看看参数。

如果您的方法对作为参数给出的对象执行某些操作,则它需要一组特定的操作。如果一种类型已经具有这些操作,则无需深入类型层次结构。这样,您的方法可以更灵活地使用。另一方面,如果你的方法做了一些只应该对某种类型做的事情,尽管超类型已经提供了所需的操作,你应该更具体。

对于返回类型,情况正好相反。如果您有特定类型,为什么将其作为超类型之一返回?它只会限制客户端可以对返回的对象调用的操作。更糟糕的是,一些开发人员可能会开始进行类型检查和强制转换才能做到这一点。

虽然其他答案在形式上大多是正确的(Liskov Substitution Principle),但我想我会给出更实际的解释。希望能帮助到你。

于 2013-08-08T11:41:41.653 回答