面向对象
什么是面向对象?
先思考一下,如果你接触过C语言,那么你知道它是面向过程的,如果用C语言来编程实现某一种功能,我们需要分析解决问题的步骤,根据步骤一步步执行,最后达到目的。例如:我们需要一辆汽车,那么面向过程就会思考,汽车的车身、轮子这些如何来制造,先制造车身,然后制造轮子,最后再拼接起来。
然后来谈谈面向对象,如果和上面一样的问题,面向对象会将问题拆分为多个对象,然后关注对象之间的行为。例如:我们需要一辆汽车,汽车有车身和轮子两个构件,它们如何生成我不关心,我可以通过别人购买得到,接着就是把它们组装起来。
面向过程和面向对象的区别
通过上面的一个小例子,我想你可以体会到面向对象和面向过程的区别,在这里总结一下:
①出发点不同。面向对象更符合常规思维方式处理客观世界的问题,强调把问题域的要领直接映射到对象及对象之间接口上。面向对象则更强调过程的抽象化和模块化,它是以过程为中心处理客观世界的问题。
②层次逻辑关系不同。面向对象用类的概念模拟了客观世界,以对象作为处理问题的基本单位,对象之间的调用关系来作为解决问题的方法。面向过程处理问题的基本单位是表达过程的模块,用模块来概括模块和模块间关系和功能,把客观世界的问题抽象成计算机处理的过程。
③数据处理方式与控制程序不同。面向对象是将数据和代码块封装成一个整体,对象的修改只能由自身的成员方法来完成,控制程序方式是通过“事件驱动”来完成。面向过程是通过程序处理数据,处理完毕后显示结果,控制程序方式是调用或返回程序,各个模块之间存在控制和被控制、调用和被调用的关系。
④分析设计与编码转换方式不同。面向对象贯穿于软件生命周期的分析、设计及编码中,从分析到设计到编码是采用一致性模型,实现的是一种无缝连接。面向过程强调分析、设计、编码之间按照规则转换,贯穿软件生命周期的是一种有缝的连接。
面向对象的特征
①抽象。
忽略与主题无关的那些方面,更充分注意与目标有关的方面。不考虑问题的全部细节,只是选择其中的一部分。抽象又包括两个方面:过程抽象、数据抽象。
②继承。
继承可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过extends来实现继承的功能,子类自动继承父类非私有化的成员属性和方法。
③封装。
封装是把描述一个对象的属性和方法代码封装在一个类中,对外部进行隐藏。类中可通过调用get/set方法来对隐藏的对象属性进行修改。
④多态。
多态是在声明时使用父类,在调用或实现时使用子类,不修改程序代码就能改变程序运行绑定的代码,让程序可以出现多个运行状态。
多态的实现机制
在Java语言中,多态语言有两种表现方法:
①方法的重载:(Overload)
重载是指同一个类中有多个同名的方法,但这些方法有不同的参数,在编译时会根据参数决定调用的方法,它是一种编译时多态。同时重载可以被看作一个方法中的方法多态性。
②方法的重写:(Override)
首先方法重写的前提是继承关系,子类可以通过重写父类的方法,让同样的方法在父类和子类中有着不同的表现形式。父类引用不仅可以指向父类的实例对象,也可以指向子类的实例对象。在程序运行时调用方法才会进行动态绑定,会调用具体实例对象的方法,也因为如此实现了多态。由于只有在运行时才能确定调用哪个方法,因此方法重写实现的多态也被称为运行时多态。它也被看作父子类的方法多态性。
重载的特点
①重载跟返回值类型、访问权限无关
②重载是通过不同的方法参数来区分的(不同参数个数、不同参数类型、不同参数顺序)
示例如下:
public class TestOverload {
// #1
public int test(int i) {
return i;
}
// #2 2和1是不同参数个数重载
public int test(int i,short j) {
return i+j;
}
// #3 3和1是不同参数类型重载
public int test(String i) {
return 0;
}
// #4 注意:4和1不是重载,返回值类型改变,编译不能通过
public double test(int i) {
return 2.0f;
}
// #5 5和2是不同参数顺序重载
public int test(short j,int i) {
return i+j;
}
// #6 注意:6和1不是重载,访问修饰符改变,编译不能通过
protected int test(int i) {
return i;
}
}
重写的特点
①重写的方法必须和父类有着相同的方法名、返回值类型和参数
②重写方法抛出异常和被重写方法所抛出异常一致
③访问修饰符的限制要大于被重写方法的范围
④父类私有方法无法重写
示例如下:
class Dad{
public void say() {
System.out.println("父类");
}
protected void go() {
System.out.println("父亲走");
}
protected void jump() {
System.out.println("父亲跳");
}
}
public class TestOverride extends Dad{
@Override
public void say() {
System.out.println("子类");
}
@Override
// 把修饰符从protected改成private,编译不能通过
private void go() {
System.out.println("儿子走");
}
@Override
// 把修饰符从protected改成public,编译通过
public void jump() {
// TODO Auto-generated method stub
System.out.println("儿子跳");
}
}