人世繁华|进行面向对象程序设计深剖,可以一学,大牛带你深入Java核心技术( 二 )


特别需要说明的是 , 一个对象既不能直接访问另一个对象内部的数据 , 也不能让其他对象直接访问自己内部的数据 。 对象之间的所有通信都是通过方法调用完成的 。 通过封装对象数据 , 最大限度地提高可重用性 , 减少数据的依赖性 , 并将程序的调试时间降到最短 。
当然 , 如同过程化程序设计语言中的模块一样 , 不要让一个对象承担的任务过多 。 创建一个仅执行少量任务的小型对象 , 会使设计和调试过程简化;而创建一个内部含有复杂数据和数百个过程的对象 , 会使设计与调试过程变得非常困难 。
OOP词汇表
在进一步学习Java之前 , 有必要弄清一些OOP的术语 。 其中最重要的是类 , 有关类的使用在第3章中的示例代码中已经看到过 。 类是构造对象的模板或蓝图 。 我们可以把类想象为小甜饼的切割机 , 把对象想象为小甜饼 。 由类构造对象的过程被称为创建类的实例 。
正如所看到的那样 , 用Java编写的全部代码都位于某个类的内部 。 标准的Java类库提供了数千个类 , 可以用于用户界面设计、日期、日历和网络程序设计等多种用途 。 尽管如此 , 仍然需要用Java创建自己的类来描述问题域中的对象 , 或使标准类库中提供的类适应用户的需求 。
封装(encapsulation , 有时称为数据隐藏)是与对象有关的一个重要概念 。 从形式上看 , 封装不过是将数据和行为结合在一个包中 , 并对对象的使用者隐藏了数据的实现方式 。 对象中的数据被称为实例域(instancefield) , 操纵数据的过程被称为方法(method) 。 对于每个特定的类对象实例都有一组特定的实例域值 。 这些值的集合就是这个对象的当前状态(state) 。 无论何时 , 只要向对象发送一个消息 , 它的状态就有可能发生改变 。
实现封装的关键在于绝对不能让类中的方法直接访问其他类的实例域 , 但可以访问它自己类的实例域 , 这一点要反复强调 。 程序仅通过对象的方法与对象数据进行交互 。 封装给予对象“黑盒”特征 , 这是提高重用性和可靠性的关键 。 这意味着一个类可以全面地改变存储数据的方式 , 只要依旧使用同样的方法操作数据 , 就不会有其他的对象知晓或在意操作过程所发生的变化 。
OOP的另一个原则会让用户自定义Java类变得轻而易举 , 这就是:类可以通过扩展另一个类来建立 。 事实上 , 在Java中 , 所有的类都源自于一个“神通广大的超类” , 它就是Object 。 在下一章中 , 将可以看到有关Object类的详细介绍 。
在扩展一个已有的类时 , 新的类具有所扩展的类的全部属性和方法 。 在新的类中 , 只需要提供那些应用于新类的新方法和数据域就可以了 。 通过扩展一个类来建立另外一个类的过程被称为继承 , 有关继承的更加详细的内容请参阅下一章 。
对象
要想使用OOP , 一定要清楚对象的三个主要特性:
?对象的行为(behavior)—可以对对象施加哪些操作 , 或可以对对象施加哪些方法?
?对象的状态(state)—当施加那些方法时 , 对象如何响应?
?对象的标识(identity)—如何区分具有相同行为与状态的不同对象?
同一个类的所有对象实例由于支持相同的行为而具有家族的相似性 。 对象的行为是用可调用的方法定义的 。
此外 , 每个对象都保存着描述当前特征的信息 。 这就是对象的状态 。 对象的状态可能会随着时间而发生改变 , 但这种改变不会是自发的 。 对象状态的改变必须通过调用方法实现 。 (如果没有经过方法调用而改变对象状态 , 就说明封装性一定遭到了破坏 。 )
但是 , 对象的状态并不能完全描述一个对象 。 每个对象都有一个唯一的身份 。 例如 , 在一个订单处理系统中 , 任何两个订单都存在着不同之处 , 即使所订购的货物完全相同也是如此 。
需要注意 , 作为一个类的实例 , 每个对象的标识永远是不同的 , 但状态却常常存在着差异 。


推荐阅读