面向对象
一、一切皆对象
Java中除了基本数据类型之外的都是对象,可称为一切皆对象。对象具有状态,用属性来描述或表达其状态;对象具有行为,
用方法来描述对象的行为。而这些属性和行为就代表了对象所具有的独一无二的特征。
面向对象技术基于对象概念,以对象为中心,以类和继承为构造机制,充分利用接口和多态提供灵活性,来认识、理解、刻画
客观世界和设计、构建相应的软件系统。
面向对象的方式由面向对象分析(OOA)、面向对象设计(OOD)和面向对象编程(OOP)三部分组成。
用方法来描述对象的行为。而这些属性和行为就代表了对象所具有的独一无二的特征。
面向对象技术基于对象概念,以对象为中心,以类和继承为构造机制,充分利用接口和多态提供灵活性,来认识、理解、刻画
客观世界和设计、构建相应的软件系统。
面向对象的方式由面向对象分析(OOA)、面向对象设计(OOD)和面向对象编程(OOP)三部分组成。
二、对象的三特征
1 封装(Encapsulation)
将对象的实现细节隐藏起来(属性、方法不对外公开),通过一些公共方法来暴露该对象的功能。
封装将实例变量标记为私有:private;
提供public的get和set方法来控制存取动作;
封装隐藏了类的细节,封装后的代码更具有安全性、可扩展性和可维护性;
将对象的实现细节隐藏起来(属性、方法不对外公开),通过一些公共方法来暴露该对象的功能。
public class Person {
private int age; // 私有属性
private String name;
public Person(){ } // 默认构造
public Person(String name,int age){ // 构造
this.setName(name);
this.setAge(age);
}
public String getName(){ return name; } // 私有属性对外提供的访问方法
public void setName(String name){ this.name = name; }
public int getage(){ return age; }
public void setAge(int age){ this.age = age;}
}
public class Student extends Person{
private int id;
public Student(){}
public Student(int id,String name,int age){
super(name,age); //
this.setId(id);
}
public int getId(){ return(id); }
public void setId(int id){ this.id = id; }
}
封装的特征:封装将实例变量标记为私有:private;
提供public的get和set方法来控制存取动作;
封装隐藏了类的细节,封装后的代码更具有安全性、可扩展性和可维护性;
2 继承(Inheritance)
继承是复用类的方法。当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法,且子类可能拥有比父类
更多的属性和方法。
继承是复用类的方法。当子类继承父类后,子类作为一种特殊的父类,将直接获得父类的属性和方法,且子类可能拥有比父类
更多的属性和方法。
继承的特征:
把一些类的共性抽取出来,放到一个类中,那么这个类就是这些具有共性类的父类,或者说这些子类继承自父类;
继承意味着子类继承了父类的成员,包括实例变量和方法;
继承分为单继承和多继承,Java被设计为单继承;
把一些类的共性抽取出来,放到一个类中,那么这个类就是这些具有共性类的父类,或者说这些子类继承自父类;
继承意味着子类继承了父类的成员,包括实例变量和方法;
继承分为单继承和多继承,Java被设计为单继承;
3 多态(Polymorphism)
一个对象,多种形态。子类对象可直接赋给父类对象的引用,或者说把子类对象当作父类对象使用。多态性的意义在于,类的
对象能以各自不同的方式响应同一消息,即“同一接口,多种方式”。多态性使得程序发出一个消息后,不同的消息接受者执行不同
的响应。
一个对象,多种形态。子类对象可直接赋给父类对象的引用,或者说把子类对象当作父类对象使用。多态性的意义在于,类的
对象能以各自不同的方式响应同一消息,即“同一接口,多种方式”。多态性使得程序发出一个消息后,不同的消息接受者执行不同
的响应。
多态的特征:
引用与对象可以是不同的类型;
引用类型可以是实际对象类型的父类;
参数和返回类型可以是多态;
引用与对象可以是不同的类型;
引用类型可以是实际对象类型的父类;
参数和返回类型可以是多态;
对象多态的核心问题:
1.若把子类对象当做父类对象,那么就只能访问父类中已有定义的属性和方法。问题是到底能访问什么呢?
成员变量与引用变量所声明的类型的成员变量绑定(静态绑定/编译期绑定)。
b. 实例方法与引用变量实际引用的对象的方法绑定(动态绑定/运行期绑定)。
实例方法与实际引用f指向的对象orange的方法绑定。
c. 静态方法与引用变量所声明的类型的方法绑定(静态绑定/编译期绑定)。
静态方法与fruit类型的方法绑定。
2.若子类把父类的方法覆盖,再把子类对象当作父类对象来看,去调用该方法,调用的是覆盖后的方法(子类中定义的方法)。
访问的是什么呢?
实例方法与引用变量实际引用的对象的方法绑定(动态绑定)。
Fruit有eat()方法,若子类Orange不覆盖(重写)eat()方法,则该对象在调用此方法时fru.eat(),先在子类里找eat(),找不到就
调用Fruit的eat()方法。若子类重写(覆盖)该方法,则调用重写后的方法。
1.若把子类对象当做父类对象,那么就只能访问父类中已有定义的属性和方法。问题是到底能访问什么呢?
Fruit fru = new Orange();
a. 能访问成员变量(包括静态变量和实例变量)。成员变量与引用变量所声明的类型的成员变量绑定(静态绑定/编译期绑定)。
b. 实例方法与引用变量实际引用的对象的方法绑定(动态绑定/运行期绑定)。
实例方法与实际引用f指向的对象orange的方法绑定。
c. 静态方法与引用变量所声明的类型的方法绑定(静态绑定/编译期绑定)。
静态方法与fruit类型的方法绑定。
2.若子类把父类的方法覆盖,再把子类对象当作父类对象来看,去调用该方法,调用的是覆盖后的方法(子类中定义的方法)。
访问的是什么呢?
实例方法与引用变量实际引用的对象的方法绑定(动态绑定)。
Fruit有eat()方法,若子类Orange不覆盖(重写)eat()方法,则该对象在调用此方法时fru.eat(),先在子类里找eat(),找不到就
调用Fruit的eat()方法。若子类重写(覆盖)该方法,则调用重写后的方法。
修订:
参考:
《Java编程思想》 第四版 Bruce Eckel著 陈昊鹏译 机械工业出版社 2007
注: