面向对象编程概念
1. 对象
对象是理解面向对象编程(OOP)技术的关键概念。举例来说,你身边的事物,一支笔、一个椅子、一只狗,都是现实生活中的对象。这些现实对象都具有两个特征:状态和行为。
狗的状态:名字,颜色,是否饥饿。狗的行为:跑,叫,躺等等;
椅子的状态:颜色,高度,长度,材质。椅子的行为:折叠。
面向对象编程中对象的概念类似于现实生活中对象的概念,面向对象编程中的对象具有属性(状态)和方法(行为),对应着现实生活中对象的状态和行为。
1.1 数据封装
通过方法对对象的内部状态进行操作,并作为对象到对象通信的主要机制。一个对象隐藏所有的内部状态,并且要求所有的对象交互行为通过已知的方法来进行,这种机制称为数据封装。
数据封装是面向对象编程概念的一个基础原则。
1.2 使用对象的好处
- 模块化:一个对象的源代码可以独立于其他对象的源代码来编写和维护。一旦创建,一个对象就可以很容易地在系统内部传递。
- 信息隐藏:通过数据封装,外部世界看不到对象内部的实现细节。
- 代码复用:可以复用已经实现的对象代码。
- 可插拔性和调试容易:如果一个特定的对象被证明是有问题,那么可以用其他对象来替换这个对象,就像现实世界中机器维修一样,一个螺母损坏,替换掉它就ok了,并不需要替换整个机器。
2. 类
类是创建单个对象的蓝图,换句话说,对象是类的实例。
在现实生活中,你会发现许多对象都是同一个类别,比如各种各样的自行车,同属于自行车类。在面向对象的术语中,我们会说一个具体的自行车是一个自行车类的一个实例。
这里是一个自行车类:
class Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
在BicycleDemo中,用Bicycle类实例化两个自行车对象:
class BicycleDemo {
public static void main(String[] args) {
// Create two different
// Bicycle objects
Bicycle bike1 = new Bicycle();
Bicycle bike2 = new Bicycle();
// Invoke methods on
// those objects
bike1.changeCadence(50);
bike1.speedUp(10);
bike1.changeGear(2);
bike1.printStates();
bike2.changeCadence(50);
bike2.speedUp(10);
bike2.changeGear(2);
bike2.changeCadence(40);
bike2.speedUp(10);
bike2.changeGear(3);
bike2.printStates();
}
}
3. 继承
不同类的对象之间具有一定数量的共同点。
山地自行车,公路自行车,双人自行车等等。例如,山地自行车、公路自行车和双人自行车都具有自行车的特征(当前速度、当前踏板节奏、当前档位)。 然而,每一种都定义了使它们与众不同的附加功能:双人自行车有两个座位和两组车把; 公路自行车有下降车把; 一些山地自行车有一个额外的链环,使它们的传动比较低。
面向对象编程允许类从其他类继承常用的状态和行为。
在下图中,Bicycle是Mountain Bike, Road Bike, Tandem Bike的超类。
在Java中,每一个子类允许有一个超类,而每一个超类可以拥有无限数量的子类。
用extends关键字创建子类,创建子类的语法如下:
class MountainBike extends Bicycle {
// new fields and methods defining
// a mountain bike would go here
}
Mountain Bike继承了Bicycle类中的所有属性和方法,继承使得子类专注于其与众不同独特的属性和方法的实现。
4. 接口
我们已经学过,对象通过方法与外界的对象进行交互,则方法形成了与外界对象交互的接口。
在最常见的形式中,接口是一组具有空主体的相关方法。
如果指定为接口,自行车的行为可能如下:
interface Bicycle {
// wheel revolutions per minute
void changeCadence(int newValue);
void changeGear(int newValue);
void speedUp(int increment);
void applyBrakes(int decrement);
}
为了实现这个接口,假设我们现在要用ACMEBicycle这个品牌的自行车来实现接口,用关键字implements来声明:
class ACMEBicycle implements Bicycle {
int cadence = 0;
int speed = 0;
int gear = 1;
// The compiler will now require that methods
// changeCadence, changeGear, speedUp, and applyBrakes
// all be implemented. Compilation will fail if those
// methods are missing from this class.
void changeCadence(int newValue) {
cadence = newValue;
}
void changeGear(int newValue) {
gear = newValue;
}
void speedUp(int increment) {
speed = speed + increment;
}
void applyBrakes(int decrement) {
speed = speed - decrement;
}
void printStates() {
System.out.println("cadence:" +
cadence + " speed:" +
speed + " gear:" + gear);
}
}
实现一个接口允许一个类对于它承诺提供的行为变得更加正式。
如果一个类使用implements关键字声称实现了一个接口,那么在这个类被成功编译之前,接口中的所有方法都必须出现在这个类的源代码中。
5. Package
Package是组织一系列相关的类和接口的命名空间,可以理解为计算机上不同的文件夹。因为在实际的应用和开发中,会有很多的类和接口的产生,通过将相关的类和接口放入包中来组织事物是有意义的。