前段时间我读过OOP的“约定”,但我不确定我是否记得正确。
它表示方法必须将继承层次结构中最通用的对象作为参数,而返回最后代的对象。
这是真的,如果是的话,有人可以解释一下吗?
示例:
IList<T> someMethod(IList<T> someList)
{
IList<T> resultList = new List<T>();
... do something with resultList ...
return resultList;
}
根据'惯例',上面的方法应该返回List而不是IList?
答案 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
更适合并提供更好的性能。现在,您必须修改函数的返回类型,并且新版本将与旧版本不兼容,因为您更改了公共方法的返回类型。
因此,虽然对于方法参数几乎总是如此,但在返回类型时会变得更复杂。 在处理论证时,你应该问问自己:
在处理返回类型时,另一方面:
答案 4 :(得分:1)
以前从未听过这样的声音,但这有道理。我们先来看看参数。
如果您的方法使用作为参数给出的对象执行某些操作,则需要一组特定的操作。如果一种类型已经具有这些操作,则不需要更深入地进行类型层次化。这样您的方法可以更灵活地使用。另一方面,如果你的方法只做某种类型的事情,虽然超类型已经提供了所需的操作,你应该更具体。
对于返回类型,它是另一种方式。如果你有一个特定的类型,为什么要将它作为其中一种超类型返回?它只会限制客户端可以调用返回对象的操作。更糟糕的是,一些开发人员可能会开始进行类型检查并进行强制转换。
虽然其他答案大部分都是正式的(Liskov Substitution Principle),但我认为我会给出一些更实际的解释。希望它有所帮助。