对于两个对象同一的理解

文件所标注的页数引自书籍《计算机程序的构造和解释》第二版,ISBN: 9787111135104

所谓两个对象同一就是指在任意时刻这两个对象对外界造成的影响完全一致(这里所说的对外界造成的影响并不单单是指对象最终求得的值对外界的影响,还包括其它的影响,例如在对象中使用赋值改变外部变量的值(参见p151)),也就是具有引用透明性(参见p159)

 

首先来看看什么情况下两个对象不同一。下面这三个命题同时为真,是两个对象不同一的充分不必要条件(两个对象不同一的具体例子参见p170图3-10)。
1.两个对象具有随时间变化的状态(用静态局部变量来表示,非静态的局部变量不行)
2.两个对象的状态变化不能做到完全一致
3.这种状态变化能够直接或间接的影响到外界或者说能被外界感知

下面三段分别就这几个因素进行解释。

什么样的对象具有随时间变化的状态呢?首先,对象需要具有静态的局部变量(非静态的局部变量或外部变量不行);然后,静态局部变量的值必须能够随着时间发生变化,也就是说需要将赋值应用到静态局部变量上(注意,如果仅仅是定义了一个赋值过程,但没有执行的话不算)。举个例子,p151的withdraw对象使用了赋值,但其并不具有随时间变化的状态(因为其自身并没有静态局部变量,赋值的作用对象是外部变量)

什么叫对象状态的变化完全一致呢?你可以这样理解,假设内存中有两个一模一样的对象,这两个对象具有随时间变化的状态,且这种状态的变化能够影响到外界。现在cpu反复并发执行这两个对象,假设两个对象的初始时间和执行速度都完全一致,那么很明显,在任意时刻,这两个对象对外界造成的影响都是完全一致的。那么外界也就无法对着两个对象进行区分,从而可以认为这两个对象是同一的。

至于状态变化直接或间接的影响到外界,首先,如果你以状态的值作为对象的值,那么可以认为这是状态变化直接影响到外界,然后,说到状态变化间接影响外界稍微复杂一点,可以举个例子。仍旧拿p151的withdraw对象来举例,可以稍微对其进行修改,对象内加一个静态的局部变量,然后每次执行withdraw对象的时候按照一定规则用赋值修改静态局部变量的值,然后根据静态局部变量的值和amout的值来给外部变量balance赋值,这样,外部变量的值就受到了withdraw对象状态变化的间接影响。n那么,理解了状态变量影响外界的情况,对于状态变量不影响外界的情况也就很好解释了。举个例子,虽然状态变量随着时间不断在变化,但对象并没有将这种变化通过直接或间接的方式透露给外界,那么状态变量就无法影响到外界,外界也就不知道对象具有随时间变化的状态,从而认为对象没有随时间变化的状态。

那么什么情况下两个对象同一呢?下面这四个命题的任意一个为真是两个对象同一的充分不必要条件

1.两个对象占据物理内存中的同一块区域,也就是说两个对象用eq?判定相等。
例如p177的图3-16中,(car z1)和(cdr z1)实际是物理内存中的同一个对象,所以(eq? (car z1) (cdr z1))为真。这里的同一,是物理存储上的同一,即使对象有执行赋值过程也不影响两个对象的同一性。p160脚注中所说的别名,也是指的这种同一。

2.两个对象占据不同的物理内存(对象可以有部分内容共享物理内存),用equal?判定相等,不具有随时间变化的状态

3.两个对象占据不同的物理内存(对象可以有部分内容共享物理内存),用equal?判定相等,具有随时间变化的状态,两个对象的状态变化完全一致

4.两个对象占据不同的物理内存(对象可以有部分内容共享物理内存),用equal?判定相等,具有随时间变化的状态,两个对象的状态变化不完全一致,状态变化无法影响到外界

此条目发表在 ., 抽象 分类目录。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>