前不久参加了一个公司的面试,然后面试官问到了一个问题:如何理解java中的面向对象思想?
当时突然有点紧张,因为确实答不出来,就直接用Java中的集合框架拿出来展开了。因为框架的设计的很多,体现了面向对象编程的一面。
当时核心的问题问到了,为什么要采用面向接口编程这种模式? 因为其他的集合实现类都是继承自一个Collection借口,此借口中有一个方法叫做iterator(),返回一个Iterator对象,使用对象的hasNext() , next()方法来遍历集合中的元素,所有实现类都实现了这个方法。
下面来看2个程序的区别,这里就不用集合类来演示了。
程序一:
package com.OOD;
public class OOD {
public static void main(String[] args) {
toCall(new A());
toCall(new B());
toCall(new C());
}
public static void toCall(Object o) {
if(o instanceof A) {
A a = new A();
a = (A)o;
a.call();
}else if(o instanceof B) {
B b = new B();
b = (B)o;
b.call();
}else if(o instanceof C) {
C c = new C();
c = (C)o;
c.call();
}
}
}
class A {
public void call() {
System.out.println("Call A");
}
}
class B {
public void call() {
System.out.println("Call B");
}
}
class C {
public void call() {
System.out.println("Call C");
}
}
该程序有3个类:A,B,C
他们内部都有自己的call()方法,而这3个类没有一点联系,除了他们都继承自Object类。
在OOD类里面有一个方法,是用统一的一个toCall方法,调用传入的参数自己的call方法。
由于这3个类的联系仅仅只是都继承了Object,所以参数可以设置为一个Object类型,来接收不一样类型的对象。
当接受到一个对象时,首先先要判断这个对象是哪个类的实例,然后强制转换之后,才能正确的调用call方法(因为Object没有call这个方法,o是一个Object的引用)。虽然可以暂时解决问题,但是从设计的角度上来说,如果有新的类加入了,比如D类,那么需要在OOD的toCall方法中加以修改才能正确运行。
再看另一种方法,这些类都实现一个接口。
package com.OOD;
public class OOD {
public static void main(String[] args) {
toCall(new A());
toCall(new B());
toCall(new C());
}
public static void toCall(Father f) {
f.call();
}
}
class A implements Father {
public void call() {
System.out.println("Call A");
}
}
class B implements Father {
public void call() {
System.out.println("Call B");
}
}
class C implements Father {
public void call() {
System.out.println("Call C");
}
}
interface Father {
public void call();
}
这些类现在的共同点是都实现了一个叫做Father的接口,并且重写了call方法。
现在看看toCall方法,参数由原来的Object类型变成了Father类型,传进来的都是一个Father引用,我不用关心这个实例具体指的是哪个对象,他是一种Father,他就带有一个call方法。所以直接在代码里面写上f.call()方法 就可以达到要求了。而当有新的类来时,只要实现Father接口,重写call方法,toCall方法的代码就不需要改了。这样的设计,比起上面的例子,是不是好了很多呢?