我的理解是术语“referential transparency”实际上只能应用于功能代码。但是,对面向对象代码中的对象的方法调用可以具有类似的属性,即方法的返回值和方法调用后的对象的状态仅取决于调用之前对象的状态,以及方法的论点。
即。功能参照透明度:
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()
的状态没有改变,则“面向对象”样式等同于函数形式,如果支持function overloading,则可能是改写为:
i = foo(obj, n, m);
// return value depends only on obj, n, m
但是,obj
的状态在方法调用中更改是很常见的,所以我不确定这是否有助于分析......
答案 0 :(得分:17)
你的错误在于认为FP和OO在某种程度上是根本不同的。参考透明度的“OO版本”只是参考透明度。
当且仅当e
可以用其评估结果替换而不影响程序的行为时,表达式e
是引用透明的。
因此,如果您有一个表达式o.foo(a)
,那么如果您可以修改代码以将其替换为调用结果,那么它将是引用透明的,而不会更改程序的行为方式。显然,如果o.foo无效,你就不能这样做。同上,如果它修改了o
的内部状态。因此,o.foo(a)
引用透明的唯一方法是,其结果是 o
和a
的函数。
在我看来,“功能代码”与“引用透明代码”同义。
答案 1 :(得分:4)
如您所说,功能术语将是参考透明度。我谦卑地建议你在这里描述的表单结果取决于方法的参数加上对象的状态被称为引用不透明度。
答案 2 :(得分: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
。
答案 3 :(得分:2)
方法调用后对象的状态仅取决于调用前对象的状态以及方法的参数。
我想你可以说方法没有外部依赖。
与参考透明度不同,我不确定这会给你带来什么。我想这意味着该方法很容易测试。