class Person { /** * 姓名 */ public $name; /** * 年龄 */ public $age; /** * 性别 */ public $sex; /** * 说话 */ public function say() { } /** * 制造工具 */ public function makeTool() { } /** * 思考 */ public function ponder() { } }
抽象是从众多的事物中抽取出共同的、本质性的特征,而舍弃其非本质的特征。
这句话是我从百度百科当中复制过来的,也许,有许多程序员都是以上述定义来描述抽象,包括我,那么我们就来分析一下这个定义。
准确的说,这是一个哲学中抽象的定义,它强调了所提取的特征必须是共同的、本质性的,我们以此为依据来看看上面的 Person,你有没有发现一些不妙的地方?我们在 Person 中定义的属性与方法中,有一部分并非是本质性的:
人没有姓名就不能称之为人了吗?
人不能说话就不能称之为人了吗?
年龄、性别是人的本质吗?
我记得以前某门科目的教科书上关于人的描述主要有两点:能够制造工具以及能够思考;参考这个,也许我们的 Person 中只会剩下 makeTool 和 ponder 这两个方法了。
哲学已经存在了许多年,而软件开发仅仅是近年才兴起的事物,我相信软件开发中的抽象一定是来源于哲学的,我们甚至沿用了哲学当中关于抽象的定义(也许有专门的定义,请知道的朋友告诉我)。但是软件开发当中的抽象却做出了改变,这种改变是什么促使的呢?
我们先来看看如何使用 Person:
$xiaoming = new Person(); $xiaoming->name = "xiaoming"; $xiaoming->age = 10; $xiaoming->sex = "男";
进行上面工作之后,我们就可以使用这个对象了,很方便不是吗?是的,正是为了方便,为了更好的复用才促使我们做出了这种变通,假如我们不作变通情况会如何呢?
class Person { public function makeTool(){} public function ponder(){} } class XiaoMingPerson extends Person { public $name = "xiaoming"; public $age = 10; public $sex = "男"; public function say(){} } $xiaoming = new XiaoMingPerson();
情况是不是变的糟糕了?每当我们需要创建一个人的实例的时候,我们都不得不为他定义一个 xxxPerson,多么蛋疼的事情。也许我们有其他的方法在一定程度上简化上面的代码,比如我们为 Person 创建两个子集,一个是 “可说话的人”,一个是 “不能说话的人”,这样 say 方法在 “可说话的人” 这个子集中就算的上是本质性的了,然后 XiaoMingPerson 从 “可说话的人” 派生,但是终究很麻烦不是吗?
软件开发当中的抽象更多的强调了共同特征,而在很大程度上忽略了本质性特征。这是由我们所做的事情决定的,我们会衡量我们将要创建的实例或子集当中都有哪些共同特征,然后我们将这些共同特征一股脑的放到抽象里,最大化的复用,来实现更简单的创建子集或实例。
好吧,我又辞不达意了,我本来想多写点东西,但是仔细想想,我还是另开一篇吧,这篇的标题我也改一下,就这样了。