> For the complete documentation index, see [llms.txt](https://lvxixiao.gitbook.io/blog/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lvxixiao.gitbook.io/blog/java/note/thinking-in-java/object/dui-xiang.md).

# 面向对象

Thinking in Java

#### 抽象过程(P2)

**Alan Kay总结面向对象五个基本特征**

* 万物皆对象
* 程序是对象的集合，它们通过发送消息来告知彼此所要做的。
* 每个对象都有自己的由其他对象所构成的存在。换句话说，可以通过创建包含现有对象的包的方式来创建新类型的对象。
* 每个对象都拥有其类型。
* 某一特定类型的所有对象都可以接收同意的信息。

**Booch对对象的描述**

对象具有状态、行为和标志。这意味着每一个对象都可以拥有内部数据(它们给出了该对象的状态)和方法(它们产生行为)，并且每一个对象都可以唯一地与其他对象区分开来，具体来说，就是每一个对象在内存中都有一个唯一的地址。

#### 复用具体实现(P5)

新的类可以由任意数量、任意类型的其他对象以任意可以实现新的类中想要的功能的方式所组成。因为是在使用现有的类合成新的类，所以这种概念被称为组合，如果组合是动态发生的，那么它通常被称为聚合。

由于继承在面向对象程序设计中如此重要，所以它经常被高度强调，于是程序员新手就会有这样的对象：处处都应该使用继承。这会导致难以使用并过分复杂的设计。实际上，在建立新类时，应该首先考虑组合，因为它更加简单灵活。如果采用这种方式，设计会变得更加清晰，一旦有了一些经验之后，便能够看出必须使用继承的场合了。

#### 伴随多态的可互换对象(P8)

在处理类型的层次结构时，经常想要把一个对象不当作它所属的特定类型来对待，而是将其当作其基类的对象来对待。这使得人们可以编写出不依赖于特定类型的代码。

如果不需要知道哪一段代码会被执行，那么当添加新的子类型时，不需要更改调用它的方法，它就能够执行不同的代码。因此，编译器无法精确地了解哪一段代码将会被执行，那么它该怎么办？

编译器不可能产生传统意义上的函数调用。一个非面向对象编程的编译器产生的函数调用会引起所谓的前期绑定。这么做意味着编译器将产生对一个具体函数名字的调用，而运行时将这个调用解析到将要被执行的代码的绝对地址。然而在OOP中，程序直到运行时才能够确定代码的地址，所以当消息发送到一个泛化对象时，必须采用其他的机制。

为了解决这个问题，面向对象程序设计语言使用了后期绑定的概念。当向对象发送信息时，被调用的代码直到运行时才确定。编译器确保被调用方法的存在，并对调用参数和返回值执行类型检查(无法提供此类保证的语言被称为弱类型)，但是并不知道将被执行的确切代码。

为了执行后期绑定，Java使用一小段特殊的代码来替代绝对地址调用。这段代码使用在对象中存储的信息来计算方法体的地址。这样，根据这一小段代码的内容，每一个对象都可以具有不同的行为表现。
