这个OOP惯例是真的吗?

时间:2013-08-08 11:25:41

标签: oop

前段时间我读过OOP的“约定”,但我不确定我是否记得正确。

它表示方法必须将继承层次结构中最通用的对象作为参数,而返回最后代的对象。

这是真的,如果是的话,有人可以解释一下吗?

示例:

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

    ... do something with resultList ...

    return resultList;
}

根据'惯例',上面的方法应该返回List而不是IList?

5 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:3)

尝试阅读Liskov Substitution Principle,特别是Covariance of return types

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

  

...
  Liskov的原则对签名强加了一些标准要求   已在较新的面向对象编程语言中采用   (通常在班级而不是类型的水平;参见名义vs.   结构子类型的区别):

     
      
  • 子类型中方法参数的逆解。
  •   
  • 子类型中返回类型的协方差。
  •   
  • 子类型的方法不应抛出新的异常,除非这些例外本身   超类型方法抛出的异常子类型。
  •   

答案 2 :(得分:2)

我认为你指的是鲁棒性原则,即波斯特尔定律。您可以谷歌搜索并找到大量信息。

答案 3 :(得分:1)

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

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

同样,如果您的方法返回了IList而不是List,那么List中定义但IList中未定义的任何方法都不会可访问(除非您知道IList实际上是List并执行演员表示)。但是,这是一个比前一个更弱的规则。

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

因此,虽然对于方法参数几乎总是如此,但在返回类型时会变得更复杂。 在处理论证时,你应该问问自己:

  1. 我真的需要一个特定的类型吗?
  2. 将来我需要这种特定类型的可能性有多大?
  3. 在处理返回类型时,另一方面:

    1. 方法用户真的需要这样的特定类型吗?
    2. 用户是否需要显式转换来访问返回值的有用方法?
    3. 将来我需要更通用的返回类型的可能性有多大?

答案 4 :(得分:1)

以前从未听过这样的声音,但这有道理。我们先来看看参数。

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

对于返回类型,它是另一种方式。如果你有一个特定的类型,为什么要将它作为其中一种超类型返回?它只会限制客户端可以调用返回对象的操作。更糟糕的是,一些开发人员可能会开始进行类型检查并进行强制转换。

虽然其他答案大部分都是正式的(Liskov Substitution Principle),但我认为我会给出一些更实际的解释。希望它有所帮助。