成类,那么桌子的颜色和人的脸色都应映射成相应类的成员变量,而两者的区别就是桌子的实例在主要运作过程中颜色都不变化,其主要用于读;人的脸色在人的实例的主要运作过程中可能变化,其主要用于写。什么叫运作过程?类映射的是资源,资源可以具有功能,即成员函数,当一个实例的功能执行时,就是这个实例的运作过程。
桌子有个功能是“放东西”,当调用这个成员函数时,其中会读取颜色这个属性的值以判断放在桌子上的东西的颜色是否和桌子的颜色搭配协调。人有个功能是“泡澡”,其可以使相应实例的脸色从惨白向红润转变。但桌子也有个功能是“改变颜色”,调用它可以改变桌子的颜色。按照前面所说,颜色是属性,应该被读,但这里却在实例的运作过程中对它进行了写操作。注意前面说的是“主要运作过程”,即桌子的目的是用来“放东西”,不是“改变颜色”。如果桌子这个概念在其相应世界中主要是用来改变其颜色而不是放东西,此时桌子只不过是一个能记录颜色值的容器,而这时桌子的颜色就是状态,不是属性了。
有何意义?属性和状态都映射为成员变量,从代码上是看不出它们的区别的,但它们的语义是有严重区别的。属性是用来配置实例而状态是用来表现实例。在面向对象编程思想中,只是简单地说对象是具有属性和功能(也被称作方法)的实例,这在编写的程序所基于的世界比较复杂时显得非常地孱弱,而且就是对“属性”的错误理解,再加上“封装”这个词汇的席卷,导致出现大量的荒谬代码,后面说明。
属性和状态的差别导致出现所谓的无状态对象(在MTS――
Microsoft Transaction Server中提出,称作Stateless Component,无状态
组件),这正是对象和实例的差别――对象是实现,因此可以是一个抽象概念的实现;实例是实际存在,不能是抽象概念的实现。这在C++代码上就表现为没有成员变量的类和有成员变量的类。如下:
struct Search { virtual int search( int*, int, int ); };
Search a, b; int c[3] = { 10, 20, 5 }; a.search( c, 3, 20 );
这里就生成两个对象a和b,它们都是抽象
|