现在把函数 math.sin 赋值给 oldSin,会出现下面的疑问:
可以这么去验证,用蓝色矩形表示一个新函数,将这个新函数赋值给 math.sin,然后检查 oldSin 是否也变化了:
事实上,在将 math.sin 的入口参数,从弧度改成角度时(这个例子参PIL第六章),有如下的定义方式:
do
local oldSin = math.sin
local k = math.pi/180
math.sin = function (x)
return oldSin(x*k)
end
end
很明显,上图中,只有左边的情况才能和这里的代码吻合。
根据上面的经验,可以这么去理解 Lua 中函数的匿名性:把函数想象为一个功能块,这个功能块可以起任意名称。要使用这个功能块,就需要通过一个名称去访问它。如果把功能块的某个名称赋值给某个变量,这个变量会成为这个功能块(函数)的另一个名称罢了,和函数的其他名称毫无关系。
Java 中对象的匿名性
Java 中的对象(Object)也面临和前面 Lua 中类似的问题,很有趣,假定有一个对象,用蓝色椭圆表示,先命名为 a. 对应的代码和图示如下:
现在把这个 a 赋值给 b,会面临下面的选择:
类似前面 Lua 部分的做法,给 a 赋一个新的对象(青色的椭圆),然后检查 b 引用的是哪个椭圆就行了:
现在通过代码来检验:
Object a = new Object();
Object b = a;
System. out.println(a);
System. out.println(b);
System. out.println(a.equals(b));
b = new Object();
System. out.println(a);
System. out.println(b);
System. out.println(a.equals(b));
某次执行的结果是:
java.lang.Object@602f892f
java.lang.Object@602f892f
true
java.lang.Object@602f892f
java.lang.Object@50d79dfe
false
可以看出,在 Java 中,实际用的是上面图中左边的选项。
根据前面的经验,可以这么去理解 Java 中对象的匿名性:对象(Object)本无名,并可任意命名,将名称赋值给某个变量后,这个变量就成为这个对象的另一个名称而已。
后记
在得到文中的理解后,感到很爽,它证实了体验不同语言的积极作用。
Lua 中 table 也有匿名性的特点,和这里比较类似,因此不打算赘述了。
文中有个瑕疵,就是两部分的图形颜色的顺序不一致,不整齐,不过做图比较麻烦,就不打算调整了。
参考
PIL 6.1 http://www.lua.org/pil/6.1.html