12

我的理解是,术语“引用透明性”实际上只能应用于功能代码。但是,面向对象代码中对对象的方法调用可以具有类似的属性,即方法的返回值,而方法调用后对象的状态只取决于调用前对象的状态,以及方法的参数。

即功能参考透明度:

i = foo(n, m);
// return value depends only on n, m

OO“参考透明度”:

i = obj.foo(n, m);
// return value, and subsequent state of obj, depends 
// only on initial state of obj, n, m

这个属性有名字吗?

如果obj在调用 的过程中 的状态没有改变,那么如果支持函数重载foo(),那么“面向对象”样式等价于函数形式,因为它可以重写为:

i = foo(obj, n, m);
// return value depends only on obj, n, m

但是,在方法调用中改变状态是很常见的obj,所以我不确定这是否有助于分析......

4

4 回答 4

17

您的错误是认为 FP 和 OO 在某种程度上是根本不同的。参照透明的“OO 版本”只是参照透明。

e当且仅当e可以用其评估结果替换而不影响程序的行为时,表达式是引用透明的。

因此,如果您有一个 expression o.foo(a),那么如果您可以修改代码以将其替换为调用结果,那么它是引用透明的,而无需更改程序的行为方式。显然,如果 o.foo 是无效的,你就不能这样做。如果它修改o. 因此,实现引用透明的唯一方法o.foo(a)是其结果 oand的函数a

在我看来,“功能代码”是“引用透明代码”的同义词。

于 2010-07-07T11:59:17.310 回答
4

正如您所说,功能术语将是参考透明度。我会谦虚地建议您在此处描述的形式以及取决于方法的参数加上对象的状态的结果被称为引用不透明度

于 2010-07-05T10:01:55.470 回答
4

我不认为您在 OO 场景中描述的属性为您提供了与函数式编程中的引用透明性类似的任何东西。您描述了一个属性,其中该foo方法仅obj在以下调用中修改对象的状态:

i = obj.foo(n, m); 

但是,如果您有另一个对象引用,obj那么调用foo也会修改另一个对象的行为。由于对象之间的引用在 OO 中是必不可少的(这意味着这是一个您无法轻易避免的问题),这意味着您描述的属性并没有告诉您太多关于代码的信息。例如:

a = new Other(obj);
i = obj.foo(n, m);  // changes state of 'obj' and 'a'

如果该foo方法是引用透明的(没有修改任何状态 - 只是返回了一些结果),那么这将是一个有趣的属性 - 因为它不会修改a.

于 2010-07-05T10:08:24.180 回答
2

方法调用后对象的状态仅取决于调用前对象的状态和方法的参数。

我想您可以说该方法没有外部依赖项

然而,与参考透明度不同,我不确定这会给你带来什么。我想这意味着该方法很容易测试。

于 2010-07-05T09:52:06.540 回答