2016PT老虎送彩金
2016pt注册送体验金
Portraits
Journal
Contact
总是有人喜欢争论这类问题,到底是“函数式编程”(FP)好,还是“面向对象编程”(OOP)好。既然出了两个帮派,就有人积极地做它们的帮众,互相唾骂和鄙视。然后呢又出了一个“好好先生帮”,这个帮的人喜欢说,管它什么范式呢,能解决问题的工具就是好工具!我个人其实不属于这三帮人中的任何一个。
面向对象编程(Object-Oriented Programming)如果你看透了表面现象就会发现,其实“面向对象编程”本身没有引入很多新东西。所谓“面向对象语言”,其实就是经典的“过程式语言”(比如Pascal),加上一点抽象能力。所谓“类”和“对象”,基本是过程式语言里面的记录(record,或者叫结构,structure),它本质其实是一个从名字到数据的“映射表”(map)。你可以用名字从这个表里面提取相应的数据。比如point.x,就是用名字x从记录point里面提取相应的数据。这比起数组来是一件很方便的事情,因为你不需要记住存放数据的下标。即使你插入了新的数据成员,仍然可以用原来的名字来访问已有的数据,而不用担心下标错位的问题。
所谓“对象思想”(区别于“面向对象”),实际上就是对这种数据访问方式的进一步抽象。一个经典的例子就是平面点的数据结构。如果你把一个点存储为:
struct Point { double x; double y; } 那么你用point.x和point.y可以直接访问它的X和Y坐标。但你也可以把它存储为“极坐标”方式:
struct Point { double r; double angle; } 这样你可以用point.r和point.angle访问它的模和角度。可是现在问题来了,如果你的代码开头把Point定义为第一种XY的方式,使用point.x, point.y访问X和Y坐标,可是后来你决定改变Point的存储方式,用极坐标,你却不想修改已有的含有point.x和point.y的代码,怎么办呢?
这就是“对象思想”的价值,它让你可以通过“间接”(indirection,或者叫做“抽象”)来改变point.x和point.y的语义,从而让使用者的代码完全不用修改。虽然你的实际数据结构里面根本没有x和y这两个成员,但由于.x和.y可以被重新定义,所以你可以通过改变.x和.y的定义来“模拟”它们。在你使用point.x和point.y的时候,系统内部其实在运行两片代码,它们的作用是从r和angle计算出x和y的值。这样你的代码就感觉x和y是实际存在的成员一样,而其实它们是被临时算出来的。在Python之类的语言里面,你可以通过定义“
property
”来直接改变point.x和point.y的语义。在Java里稍微麻烦一些,你需要使用point.getX()和point.getY()这样的写法。然而它们最后的目的其实都是一样的——它们为数据访问提供了一层“间接”(抽象)。
这种抽象有时候是个好主意,它甚至可以跟量子力学的所谓“不可观测性”扯上关系。你觉得这个原子里面有10个电子?也许它们只是像point.x给你的幻觉一样,也许宇宙里根本就没有电子这种东西,也许你每次看到所谓的电子,它都是临时生成出来逗你玩的呢?然而,对象思想的价值也就到此为止了。你见过的所谓“面向对象思想”,几乎无一例外可以从这个想法推广出来。面向对象语言的绝大部分特性,其实是过程式语言早就提供的。因此我觉得,其实没有语言可以叫做“面向对象语言”。就像一个人为一个公司贡献了一点点代码,并不足以让公司以他的名字命名一样。
2016pt注册送体验金
Portraits
Journal
Contact