封装是面向对象系统的一个重要特性,是抽象数据类型思想的具体体现。
在面向对象的程序设计中,抽象数据类型是用“类”这种结构来代表的,而“类”又是面向对象的工具可理解和操纵的。
1 封装的概念
封装也称为信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外接口使之与外部发生联系。
系统的其他部分只有通过包裹在数据外面的被授权的操作来与这个抽象数据类型交流与交互。
也就是说,用户无需知道对象内部方法的实现细节,但可以根据对象提供的外部接口(对象名和参数)访问该对象。
封装具有下述特征:
在类的定义中设置访问对象属性(数据成员)及方法(成员方法)的权限,限制本类对象及其他类的对象使用的范围。
提供一个接口来描述其他对象的使用方法。
其他对象不能直接修改本对象所拥有的属性和方法。
封装反映了事物的相对独立性。
封装在编程上的作用是使对象以外的部分不能随意存取对象的内部数据(属性),从而有效地避免了外部错误对它的“交叉感染”。
另一方面,当对象的内部做了某些修改时,由于它只通过少量的接口对外提供服务,因此大大减少了内部的修改对外部的影响。
面向对象系统的封装单位是对象,类概念本身也具有封装的意义,因为对象的特性是由它所属的类说明来描述的。
2 类的严谨定义
[类修饰符] class 类名 [extends 父类名] [implements 接口列表]
{
数据成员
成员方法
}
合理地使用这些可选项,可以充分地展示封装、继承和信息隐藏等面向对象特性。
类修饰符(Qualifier):用于规定类的一些特殊性,主要是说明对它的访问限制。
extends 父类名:指明新定义的类是由已存在的父类派生出来的。
implements 接口列表:Java 本来只支持单继承,为了给多重继承的软件开发提供方便,它提供了这一接口机制。
3 类修饰符
类的修饰符用于说明对它的访问限制,一个类可以没有修饰符,也可以有 public、final、abstract 等几种不同的修饰符。
3.1 无修饰符的情况
如果一个类前无修饰符,则这个类只能被同一个包里的类使用。
Java 规定,同一个程序文件中的所有类都在同一个包中。
无修饰符的类可以被同一个程序文件中的类使用,但不能被其他程序文件中的其他包中的类使用。
3.2 public 修饰符
如果一个类的修饰符是 public,则这个类是公共类。
公共类不但可供它所在包中的其他类使用,也可供其他包中的类使用。
在程序中可以用 import 语句引用其他包中的 public 类。
Java 规定,在一个程序文件中,只能定义一个 public 类,其余的类可以是无修饰符的类,也可以是用 final 修饰符定义的最终类,否则编译时会报错。
3.3 final 修饰符
用 final 修饰符修饰的类被称为最终类。
最终类是不能被任何其他类所继承的。
定义最终类的目的有三:
用来完成某种标准功能。将一个类定义为 final 类,则可以将它的内容、属性和功能固定下来,与它的类名形成稳定的映射关系,从而保证引用这个类时所实现的功能是正确无误的。
提高程序的可读性。从父类派生子类,再从子类派生子类,使软件变得越来越复杂。而在必要的层次上设置 final 类,可以提高程序的可读性。
提高安全性。病毒的闯入途径之一是在一些处理关键信息的类中派生子类,再用子类去替代原来的类。由于用 final 修饰符定义的类不能再派生子类,截断了病毒闯入的途径,因而提高了程序的安全性。
3.4 abstract 修饰符
用 abstract 修饰符修饰的类称为抽象类。
抽象类刻画了研究对象的公有行为特征,并通过继承机制将这些特征传送给它的派生类。
其作用在于将许多有关的类组织在一起,提供一个公共的基类,为派生具体类奠定基础。
此外,当一个类中出现一个或多个用 abstract 修饰符定义的方法时,则必须在这个类的前面加上 abstract 修饰符,将其定义为抽象类。
3.5 类修饰符使用注意事项
可以同时使用两个修饰符来修饰一个类,当使用两个修饰符修饰一个类时,这些修饰符之间用空格分开,写在关键字 class 之前,修饰符的顺序对类的性质没有任何影响。
需要注意的是:一个类可以为修饰为 public abstract,也可以被修饰为 public final,但不能被修饰为 abstract final,这是因为 abstract 类自身没有对象,需要派生子类后再创建子类的对象,而 final 类不能派生子类,所以不存在用 abstract final 两个修饰符修饰的类。