面向对象技术
面向对象技术
1.1 面向对象和面向过程
面向对象是,将数据和对数据操作方法作为一个相互依存的整体即为对象。对于同类对象抽象出其特性,即为类。类通过一个简单的接口与外界发生关系,对象之间通过消息进行通信。
面向过程是以事件为中心的开发方法,将功能划分为若干个基本模块。
不同点:
- 出发点不同,面向对象更符合常规思维,强调把问题直接映射到对象及对象之间的接口上;面向过程强调的是过程的抽象化和模块化,以过程为中心处理客观世界问题;
- 层次逻辑关系不同,面向对象以对象的集合类作为处理问题的基本单位,类的层次结构来体现类之间的继承和发展;面向过程处理问题的基本单位是清晰准确表达过程的模块,用模块的层次结构概括模块和模块之间的关系;
- 数据处理方式和控制程序方式不同;面向对象将数据和对应代码封装成一个整体,对象的修改只能由自身的成员函数来完成;面向过程直接通过程序来处理数据,各模块之间存在控制、被控制、调用和被调用的关系;
- 分析设计与编码转换方式不同;
1.2 面向对象有哪些特征
抽象、继承、封装、多态
- 抽象:抽象就是忽略一个主题中与当前目标中无关的方面,不需要了解全部问题,只选择其中的一部分,抽象包括过程抽象和数据抽象;
- 继承:继承实现了 IS-A 关系,例如 Cat 和 Animal 就是一种 IS-A 关系,因此 Cat 可以继承自 Animal,从而获得 Animal 非 private 的属性和方法。继承应该遵循里氏替换原则,子类对象必须能够替换掉所有父类对象。Cat 可以当做 Animal 来使用,也就是说可以使用 Animal 引用 Cat 对象。父类引用指向子类对象称为 向上转型 ;
- 封装:利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体。数据被保护在抽象数据类型的内部,尽可能地隐藏内部的细节,只保留一些对外的接口使其与外部发生联系。用户无需关心对象内部的细节,但可以通过对象对外提供的接口来访问该对象;
- 多态:多态是指允许不同类的对象对同一消息作出响应,分为编译时多态和运行时多态。
1.3 面向对象开发的优点
- 较高的开发效率,通过继承或者组合方式实现代码的重用,提高了软件开发效率;
- 保证软件的鲁棒性;
- 保证了软件的高可维护性;
1.4 继承
继承是面向对象的一个重要特性,通过继承,子类可以使用父类中的一些成员变量和方法,从而提高了代码的复用性,提高开发效率。Java中被继承的类叫父类(superclass),继承父类的类叫子类(subclass),使用格式为:class子类名 extends 父类名
特性:
- Java中不支持多继承,子类最多只有一个父类,但可以通过多接口达到多重继承;
- 子类只能继承父类的非私有的成员变量和方法;
- 子类中成员变量会覆盖父类中同名的成员变量,不会继承;
- 子类的方法会覆盖父类的方法,相同的方法名、参数个数与类型,不会继承;
1.5 组合和继承的区别
组合是指在新类里面创建原有类的对象,重复利用已有类的功能;
继承允许根据其它类的实现来定义一个类的实现;
举例分析:
Verhicle交通工具对象,Car表示汽车对象,Tire表示轮胎对象;
Car是Verhicle中的一种,是继承关系 is - a;
Car中包含了多个Tire,是组合关系 has - a;
class Vehicle{
}
class Car entends Verhicle{
}
//组合
class Tire{
}
class Car extends Verhicle{
private Tire t = new Tire();
}
1.6 多态的实现机制
多态分为编译时多态和运行时多态
- 编译时多态主要指方法的重载
- 运行时多态指程序中定义的对象引用所指向的具体类型在运行期间才确定
运行时多态有三个条件;
- 继承
- 覆盖(重写)
- 向上转型
重载和重写的区别
重载(overload)和重写(override)是Java多态性的不同表现形式;
重载是指在一个类中定义了多个同名方法,它们或有不同的参数个数或有不同的参数类型,使用重载需要注意以下几点:
- 重载是通过不同的方法的参数来区分,例如:参数个数、类型或顺序不同;
- 不能通过方法的访问权限、返回值类型和抛出的异常类型来重载;
- 对于继承来说,如果父类的访问权限是private,不能对其进行重载;
重写是指子类方法覆盖父类方法,覆盖一个方法并对其进行重写
- 子类的方法和父类中被覆盖的方法名称相同,参数相同;
- 子类的方法返回值必须和父类中被覆盖的方法的返回值相同;
- 子类中覆盖方法抛出的异常必须和父类中被覆盖方法抛出的异常一致;
- 父类中被覆盖的方法不能为private;
重载和重写的区别:
- 重写是子类和父类的关系,是垂直关系;重载是同一类中方法之间的关系,是水平关系;
- 重写只能是一个方法或者方法对产生关系,重载是多个方法之间的关系;
- 重写要求参数列表相同;重载要求参数列表不同;
- 重写关系中,调用方法是根据对象的类型来决定;重载是根据调用时的实参表和形参表来选择方法体的;
1.7 抽象类与接口有什么异同
抽象类(abstract class)和接口(interface)都是支持抽象类定义的两种机制,前者表示一个实体,后者表示一个概念,二者之间也有很大的区别。
只要包含一个抽象方法的类必须声明为抽象类,抽象类可以声明方法的存在而不去实现它,被声明为抽象的方法不能包含方法体,在实现时必须包含相同或者更低访问级别(public>protected>private),抽象类不可以实例化,但是可以创建一个对象使其指向具体子类的一个实例。
接口可以看成是抽象类的变体,接口中的所有方法都是抽象的,可以通过接口来实现多继承,接口中的成员变量都是static final类型;
接口和抽象类的相同点:
- 都不能被实例化;
- 接口的实现类或者抽象类的子类只有实现了接口或抽象类中的方法才能被实例化;
接口和抽象类的不同点:
-
接口只有定义,方法不能再接口中实现,只有实现接口的类才能实现接口中定义的方法,而抽象类可以有定义与实现,即其方法可以在抽象类中被实现;
-
接口需要implements,抽象只能被继承extends,一个类可以实现多个接口,但一个类只能继承一个抽象类;
-
接口强调特定功能实现,理念是“has-a”关系;抽象类强调所属关系,设计理念是“is-a”
-
接口中定义的成员变量默认是public static final,只能够有静态的不能被修改的数据成员,必须赋初值,其所有成员方法都是public、abstract的,只能被这两个关键字修饰。抽象类的抽象方法前(有abstract修饰)不能用private、static、synchronized、native等访问修饰符修饰,方法必须以分号结尾,不带花括号。
-
接口被运用于比较常用的功能,便于日后维护或者添加删除方法;抽象类更倾向于充当公共类的角色,不适用于日后重新对其进行代码修改;
1.8 内部类
内部类分为:静态内部类(static inner class)、成员内部类(member inner class)、局部内部类(local inner class)、匿名内部类(anonymous inner class)
非静态内部类不能有静态成员,静态内部类不能访问外部类的非静态成员;
局部内部类不能被public、protected、private以及static修饰,只能访问方法中定义为final类型的局部变量;
匿名内部类,不使用关键字class、extends、implements,没有构造函数,必须继承(extends)其它类来实现接口;
- 匿名内部类不能有构造函数;
- 匿名内部类不能定义静态成员、方法和类;
- 匿名内部类不能是public、protected、private、static;
- 只能创建匿名内部类的一个实例;
- 一个匿名内部类一定是在new的后面,这个匿名类必须继承一个父类或者实现一个接口;
- 局部内部类的所有限制对匿名内部类都有效;
1.9 如何获取父类的类名
java提供了getClass().getName();
可以通过Java的反射机制,使用getClass().getSuperclass().getName(),
1.10 this和super的区别
this用来指向当前实例对象,用来区分对象的成员变量与方法的形参;
class People{
String name;
public People(String name){
this.name = name;
}
}
super可以用来访问父类的方法或成员变量,当子类的方法或变量有相同的名字时也会覆盖父类的方法或成员变量,要想访问父类的方法或成员变量只能通过super关键字来访问;子类构造函数需要显式调用父类构造函数时,super()必须为构造函数中的第一条语句;