|
|
引言
有些时候,一些代码很难按照面向对象进行划分。有时候,面向对象会引起你思维上的不清晰,即使用了面向对象的语句的意义如何。本文将探索这些问题。。。
/* 先看看一个 C-style 的例子代码 */
Move( Player, Door );
SetHP( Player, NewHP );
// 再来看一个 C++ style的版本
Player->Move( Door );
Player->SetHP( NewHP );
上面这两个版本实际上是等价的.
前者,类似于菲律宾语等,后者类似于英语等。
现在我们看一个不同的C++版本:
Manager->Move( Player, Door );
Manager->SetHP( Player, NewHP );
这3种版本完成的都是同样的事情,
现在我们按照实际意义,用人类语言,分析代码的一下语义:
Manager->Move( Player, Door ); 这句可以用一下几种句子解释:
Move谓语,移动动词: Player主格 Door目的格
Move谓语,移动动词使役: Manager主格 Player宾格 Door目的格
Manager->SetHP( Player, NewHP ); 这句可以用一下几种句子解释:
SetHP自动词: Player主格 NewHP目的格
SetHP他动词,反身: Player主格 Player宾语 NewHP目的格
SetHP他动词: Manager主格 Player宾格 NewHP目的格
上述过程中发现的问题:
我们发现,人们在阅读代码时,对于理解第2个SetHP的语义,要比Move的思维复杂些。
实际上,当问题变得更加复杂时,尤其是在用面向对象的思想去描述剧本时,在语句叙述上有时难免要“想一下”,比如 “SetHP”这样的东西具体是什么意义?等等。
顺便说一个别的例子,比如我们现在有这样一个句子:
AAA->GiveItem( BBB, CCC ); 试问,这是什么意思?虽然“GiveItem”是一个有意义的单词,但仍然没有告诉我们整个句子的意义。
再来看一个更有意思的情况:
string->append(tmp); 这句可理解为:
append他动词: (未知)主格 string目的格 tmp宾格
append自动词: tmp主格 string目的格
append他动词被动态: string主格 tmp宾格
-----------------------------------------------------------------------------
我想,这有可能是一部分程序员不愿意用面向对象的原因之一
-----------------------------------------------------------------------------
在继续后面的论述之前,我提醒一下读者,包括我自己:
----面向对象是思想(语义),不是书写风格( C ? C++ ? )
因为面向对象引入了一个“对象”之概念,现抛开名称空间问题和软件工程等问题不谈,单就语言层面上来说,“对象”可以说是函数(动词)的参数(名词)的特殊化!
比如,不用面向对象思想:
func( a, b, c ); 这里 a,b,c 三者都是平等的;
而采用面向对象思想之后,同样用C-style以方便对比
method( pObj, s, t ); 这就变得不一样了----你心里明白,pObj是一个对象----换言之可以把对象看作是一个特殊地位的argument。
但是,这个特殊的arg----对象----其到底在句子中具有什么地位值得我们将它特殊化?
----不知道阿,有些情况下很难确定“对象”在句子中的确切意义。
此时此刻估计 C 程序员在嘲笑咱们 C++ 程序员----因为 C 程序中,对象的概念不明确,他们可以将设计重点放在具体意思上,而不是拘泥于“对象”“类”----因为C只有全局的函数,没有人强迫他们非要按照面向对象设计(如写成" layerMoveTo(player,x,y);"之类)
C++风格引起的另一个耐人寻味的问题是,实际上你已经看到过了,比如:
是设计为 Manager->Move( Player, Door ); 呢?
还是 Player->Move( Door ); 呢?
此时此刻,估计 C 程序员又在嘲笑这边了。。。
C风格的好处在于,它使得程序员将注意力集中在问题的客观的处理上,而不是“接近于一个人做一个事,比较贴近生活”,后者经常被认为是OO的好处----但实际上,我们以上的论述实际上已经表明了:
-----------------------------------------------------------------------------
面向对象,并不意味着,类似于“一个人做一个事,比较贴近生活”
-----------------------------------------------------------------------------
让我们悲观一点,极端情况下,OO会让你的思维变得不必要的复杂,而实际上 C 程序员可以轻松搞定你的问题。
但是,实践证明OO思想在这个地方异常出色(至少!):
-----------------------------------------------------------------------------
用户界面
-----------------------------------------------------------------------------
没有用过vb6, .net等现代UI库的朋友,在反驳我这句话之前请先调查一下。
我的一个比较极端的观点,OO == 用户界面。
回到正题,因为我们不只关注UI,所以我们仍然需要继续探讨先前的OO话题。
!在继续之前,请读者注意,关于符号的作用域,书写格式的问题我们不研究。比如,如果说C++风格的优点是method属于某个class的作用域之内,使得书写方便,我承认。但我们不讨论这些。
在C++风格下,总是会让我们用OO的思想来设计程序,而C风格则不管我们是否采用OO。
OO造成的负面影响(比如上文提到的那些),而C的书写风格使得我们不去拘泥于OO,而用面向过程去轻松地看待一些问题。但是----
-----------------------------------------------------------------------------
面向过程是simple的,他只是提供了一个空泛的框架,而把问题基本上扔给了我们!
-----------------------------------------------------------------------------
在OO让你的思维混乱的情况下,如果你决定这样:
func(a,b,c);
可是,在极端情况下,这样的句子很令人讨厌(特别是比如书写游戏剧本)----讨厌之处在于,句子写的太空泛,这样的代码,一眼看上去都是一成不变的函数调用,看多了会腻烦不说,意义也较难被澄清。
于是我推荐,特别是书写游戏剧本时,采用:
-----------------------------------------------------------------------------
格语法
-----------------------------------------------------------------------------
(重申一次,符号作用域问题我们不讨论。仅仅为了这个而死守OO不一定是明智的)
我们可以把一个比较有实际意义的句子,用近似于人类语言的格语法来写:
func-谓语 a-主格 b-目的格 c-宾格
因为不同人有不同的喜好,比如喜欢English,日文,中文,或者菲律宾语等等,
这些都无所谓!----既然本文不讨论书写格式----你可以用你自己喜爱的方式去书写,
只要能够基本分清这些“格”即可。例如,上面那句话实际可以有e,j,c三种实现:
a func c to b
a が c を b に func
a 将 c func 到 b
如何?读者不妨回去试试  |
|