<?xml version="1.0" encoding="GB2312" ?>
<?xml-stylesheet type="text/xsl" href="../../article.xsl" ?>

<article>

<title>OO给我们带来了什么？</title>

<author>晨光（Morning）</author>

<keywords>
  <keyword>OO</keyword>
</keywords>

<from type="原作"/>
<copyright/>

<paragraph>
OO到底给我们带来了什么影响？本文结合笔者实践的体会，试图对此做一个简单的探讨。至于更为深入、细致、完整的讨论，大家自当查阅相关书籍。此外，本文没有提及OO的负面影响。
</paragraph>

<paragraph>
这里采用了一种由特殊到一般，由简单到复杂的思考方法。
</paragraph>

<paragraph>
让我们来考虑一种极端的、也是最简单的情况，一个系统中只有一个类。
</paragraph>

<paragraph>
此时，将类的属性和对属性的操作绑定在一起，使得用这种方法描述的系统，更自然、更具逻辑、更符合人们的思维习惯。这使我们在从物理世界到软件世界的建模变得相对容易。同时也使实际编写的代码更具可读性。除此以外，OO所带给我们的并不比此前的任何一种程序设计方法要多多少。对于易于建模，其实是相对的。对于可读性，甚至可以认为并非是OO所带给我们的，一个缺乏经验的programmer，使用OO同样会写出糟糕的代码来。另外，当所有这些，经过compiler加工之后，便又回到了“原始社会”，在那里，OO世界已经不复存在了。
</paragraph>

<paragraph>
当系统变得稍微复杂一些时，出现了多个具有横向关系的类（即不考虑继承关系，至于继承则要在晚些时候再提到），OO世界中的另一个基本要素——类间关系（另一个当然是类本身了），便出现了。它会以各种可能的形式，渗透在整个系统所包含的类中：类中含有对另一个类的引用，类中方法的参数和返回值具有另一个类的类型，等等。
</paragraph>

<paragraph>
此时，类的对外接口便显得尤为重要了。对类属成员可见性的控制，使它更适于描述现实世界中的实体。作为物理世界中的实体在软件世界中的对应物，类对外表现着一定的功能，它是半封闭的，并保持一定状态（通过类属数据体现）。当外界某个条件触发其功能时（也被称作消息传递机制），它对其自身属性的操作，使之从一种状态迁移到另一种状态。另外，由于前述类间关系的存在，它也可能通过与之相关联的类所提供的接口，触发这些类的功能，进而改变它们的状态。这样的事情，在任何一个OO系统中都相当普遍，功能的触发以及由耦合所产生的“链式”反应时常会发生。
</paragraph>

<paragraph>
让我们再来考虑另一种复杂度相当的情况，在这个系统中只包含两个具有纵向关系的类。
</paragraph>

<paragraph>
此时，OO的一个重要特性——继承，登场了。在这种情形下，我们所能看到的是重用性。把易于复用的，相对稳定的内容，从一个类中抽取出来，放入另一个类。前者称为派生类（或子类），后者称为基类（或超类）。当系统加进第三个类，并且也需要基类中的代码时，它可以选择从基类派生，并对派生后的行为和属性做必要的定制（overloading／overriding）。对于一个持续发展的软件系统而言，可重用性是至关重要的。同样，从概念上讲，这种重用的方式，较之传统的类似平面结构的库函数而言，也更自然，更易于维护。
</paragraph>

<paragraph>
将前述两种情形合并，得到了最一般的，也是最复杂的情形，一个系统中包含多个类，它们彼此间具有横向和纵向的关系，或者兼而有之，或者没有任何关系。
</paragraph>

<paragraph>
此时，OO所带给我们的好处是：底耦合。在引入继承后，对于某个基类而言，系统其余部分可能与之保持着某种联系。但对于这些部分，它们只需知道基类即可，而无需认识其派生类。所以，当派生类发生改变时，一般而言，系统其余相关部分是无需改变的。同时，当引入OO的另一个重要特性——多态之后，一切变得妙不可言。因为，重载基类的虚函数，外部调用这些函数的代码无需改动，便会出现不同结果。
</paragraph>

<paragraph>
此外，对于总是和耦合一起出现的内聚，其实在前面第一种情况中，就可以看到。类中数据在类范围内是“全局”的，它们在类范围内，任何时候任何地方都可以被引用。软件工程中的耦合和内聚在程序设计语言中得到了对应实现。这使我们从设计到实现的过渡，变得相对容易。
</paragraph>

<paragraph>
在前面提到的最后一种情形中，类的封装性的作用也变得更为突出了。因为，你可以通过控制类属成员的可见性，使系统耦合得到适当降低，系统其余部分只需要知道它们该知道的信息就可以了。
</paragraph>

<paragraph>
最后指出一点，知道这些，并不等于你永远不会犯错误。尽管你或许深谙理论，却也难免时常会在代码的海洋中迷失方向。这就好像，你看懂了某个数学定理并看懂了其证明过程，为其精妙的思路所叹服，并深以为然。但你可能仍然无法很好的运用它，在实际解题的过程中发挥作用。只有这些观念根深蒂固地植入你的大脑，成为你的习惯性思维之后，你才算得上是一个经验丰富的programmer。这代表你具有了深邃的洞察力，敏锐的嗅觉。
</paragraph>

<paragraph>
个人观点，仅供参考。
</paragraph>

</article>