0.绪论
面向对象的三大特性是封装、继承和多态。本文以java为例简述这三个概念在java语言中的具体体现。
首先说明一下,在java中,一个对象就是一个java类的一个实例。在一个java类中,包括数据成员和方法成员,其中数据成员又被称为属性,方法成员简称为方法。
1.封装
1.1 概念:封装是指把对象(即java类)的属性和方法结合成一个独立的整体,隐藏实现细节,并提供对外访问的接口(接口是指外部可访问的数据成员和方法成员)。
1.2 优点/产生原因:
(1)安全性:类使用者只能通过暴露的接口去使用该类的实例,避免了类使用者对该类对象的不当操作(eg.使用者不小心修改了对象的某个私有数据成员,导致在调用该对象某个方法时结果与预想结果不一致);
(2)灵活性:在保证暴露的接口不变的情况下,类创建者可以任意修改被隐藏的部分,而不用担心对类使用者造成影响。
1.3 在java中如何实现封装
封装的实质是访问控制,其目的是控制类使用者对类中成员(包括数据成员和方法成员)的访问权限。在java中,使用public、private、protected三个关键字来进行访问控制。其中,public关键字表示紧随其后的元素对任何人都可用;private关键字表示除类型创建者和类型的内部方法之外的任何人都不能访问;protected关键字表示除类型创建者、类型的内部方法和继承类(即子类)外的任何人都不能访问。
在没有使用这三个关键字的情形下,java默认的访问权限是包访问权限,即某个类的成员可以被与该类处在同一个包中的其他类访问。(包,就是文件目录或者文件夹的意思。)
注意点:public、private和protected是java中的访问限制词,不仅可以用于修饰数据成员、方法成员,可以用于修饰class、interface等。
2.继承
2.1 概念:继承是指在已有类的基础通过修改或者添加其数据成员、方法成员形成一个新的类。
继承的层次如图2.1所示,箭头表示导出类继承了基类。已有类被称为基类或者父类,形成的新类称为导出类,也称子类。
图2.1 继承层次UML图
2.2 子类和基类可能的组合形式:
(1)子类和基类完全一致;(这种形式比较少见,与基类完全一致的子类毫无意义。)
(2)子类和基类对外提供的接口完全相同,但子类重载或重写(overriding,又称覆盖)了基类的某些方法;(关于重载和重写请阅读方法重载和重写--java)
(3)子类在基类对外提供的接口之上新添加了接口;
(4)子类既新添加了接口,又重写了基类的某些方法((2)和(3)的综合);
总结:子类可以通过方法重写或新添加数据成员、方法成员两种方式来使得自身与基类不同。
2.3 优点/产生原因:代码复用(可以通过复用基类代码创建一个与基类类似的类)
2.4 注意点:通过继承,子类对象既可以看作是子类类型,也可以看作是基类类型。但是,基类对象则只能是基类类型(除非子类与基类完全一样)。
3.多态
3.1 产生原因:多态与继承密不可分,本文2.2中提到在继承中子类与基类产生差异的方法包括重写基类方法和新添加数据成员、方法成员两种方式,新添加数据成员和方法成员的方式很自然地扩展了基类。但是,当子类重写基类方法时,该方法至少有两个不同的实现,这就带来了一个问题:程序运行该方法时如何选择该方法的具体实现?多态,正是为了解决这一问题产生的。
3.2 概念:多态,又称为后期绑定,是指当向对象发送消息时,被调用的代码直到运行时才确定。通俗一点说,多态就是指在子类重写了基类的方法(假定方法名为A)的情形下,在程序中创建一个子类对象并声明该对象类型是基类类型,调用该对象的A方法会执行子类的A方法,而不是基类中的A方法。
多态实例:在下面的代码中,在同一目录下创建了三个java文件:Base.java,Sub.java和Test.java。其中,Base.java中创建了Base类,Base类中只有一个方法A;Sub.java通过继承Base类创建了Sub类,并在Sub类中重写了Base类的A方法;最后,在Test.java中的main方法中创建了一个Sub对象eg,并且eg被声明为Base类型。调用对象eg的A方法,通过输出结果,可以看出java编译器在运行时执行的是Sub类中的A方法,而不是Base类中的A方法。这正是多态的体现。
1 //Base.java:基类 2 public class Base{ 3 public void A(){System.out.println("This is Base Class.");)} 4 } 5 6 //Sub.java:子类 7 public class Sub extends Base{ 8 public void A(){System.out.println("This is Sub Class.");} 9 } 10 11 //Test.java:多态测试 12 public class Test{ 13 public static void main(String[] args){ 14 Base eg = new Sub(); 15 eg.A(); 16 } 17 }
//输出结果
This is Sub Class.
4.总结
继承和多态是由java编译器保证的,程序开发者只需要理解其思想并按指定规则(通过extends实现继承,通过方法重写和重载实现多态)去做即可,而封装则需要程序开发者去完整实现。