子类毕竟继承了什么?(A)
Java的继承可以在结构和功能上为程序带来很好的便捷性和灵活性。但是在继承的过程中,如果不能够非常深刻的理解这其中的一些规律规则,就不能够很好的发挥继承带来的优势,甚至会造成一些错误。
继承和abstract
这三个类的代码如下:
import java.awt.event.*; public abstract class grandfather implements ActionListener { public abstract void m1(); } import java.awt.event.*; public abstract class father extends grandfather { public abstract void m2(); } import java.awt.event.*; public class son extends father { public void m1() {} public void m2() {} public void actionPerformed(ActionEvent e) {} }
在这个程序中,最原始的基类---grandfather,是一个抽象类,它有一个m1()的抽象方法。此外,grandfather还实现了ActionListener接口,按理说是需要重写接口中的actionPerformed()方法的,但由于grandfather本身是一个抽象类,就可以不覆盖actionPerformed()。(若将grandfather又抽象类改为普通类,编译将无法通过,编译器会提示:grandfather不是抽象的,并且未覆盖XXX中的抽象方法XXX(parameters) )。
按照继承的规则,其子类---father,在继承grandfather之后,需要对m1()进行重写(overriding),但碰巧的是,father自身有一个抽象方法m2(),所以father也必须也声明为一个抽象类(否则无法通过编译),这个时候,由于father是抽象类,就可以不去覆盖其基类的抽象方法了。
最后一个类,father的子类---son,是一个普通的非抽象的类,这时候,由于son不抽象,就无法逃过重写的责任了,它必须将其基类father的抽象方法m2()进行重写,不仅如此,由于其基类father未重写最原始基类grandfather的抽象方法m1()和actionPerformed(),son还需要重写这两个方法。否则会编译器无法通过编译。
也就是说,一个抽象方法最终一定会得到重写,就算第一个子类将自身定义为抽象类,逃掉了重写的责任,以后也必然会有一个非抽象的子类来完成早该完成的重写任务。当然,如果所有类都是抽象的,抽象方法就可以一直不去重写,不过这显然是不可能,也是没有意义的。
在这个程序中,我认为每个类都应该定义好自己的行为,及时的重写自己该重写的方法,这样,既可以避免许多编译无法通过的麻烦,也可以提高类的内聚性,使一个类的更加凸显出自己的作用与功能(比如说grandfather实现ActionListener的接口,肯定是需要对component进行监听,那么actionPerformed()方法理应在grandf里就实现,而不该拖到son类中实现),同时还必然为子类减轻了负担。
更加合理的代码如下:
import java.awt.event.*; public abstract class grandfather implements ActionListener { public abstract void m1(); public void actionPerformed(ActionEvent e) {} } import java.awt.event.*; public abstract class father extends grandfather { public abstract void m2(); public void m1(){}; //public void actionPerformed(ActionEvent e) //{} } import java.awt.event.*; public class son extends father { public void m2() {} //public void m1() //{} //public void actionPerformed(ActionEvent e) //{} }
此时father和son中的被注释掉的代码,视具体情况选择需不需要,father中的m1()和son中的m1(),m2(),和actionPerformed()就不仅仅为通过编译了,而是为了通过overriding与inheritance为类自身提高性能和功能,从而提高程序的效率。
……………………………………………………………………………………………………………
In the section on Interfaces, it was noted that a class that implements an interface must implement all of the interface's methods. It is possible, however, to define a class that does not implement all of the interface methods, provided that the class is declared to be abstract. For example,
abstract class X implements Y {
// implements all but one method of Y
}
class XX extends X {
// implements the remaining method in Y
}
In this case, class X must be abstract because it does not fully implement Y, but class XX does, in fact, implement Y.
……………………………………………………………………………………………………………
来自:THE JAVA TUTORIAL:Abstract Methods and Class. URL:http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
其实Java这样做也不难理解:作为一个抽象类,其本身是不可以被实例化的,所以就算有某些抽象方法没有实现或重写也无碍,反正在程序运行时这些方法不会被真正地调用(就算调用,也是跑到子类去调用被实现了的重写方法了。),但是我个人觉得抽象类应该是因为自身有抽象方法才把自己定义为抽象类的,而不能因为自身继承了其他类的抽象方法,为了不去重写而将自身抽象。
相反,作为非抽象类,如果类中存在有未实现的方法的话,无论是继承而来的,还是自身定义的,都是不被允许的,因为类本身是不抽象的,如果这个类被实例化后并且调用了那些没有实现的方法,效果相当于是空,因为调用的是抽象的方法,不能做任何事情,这也是为什么非抽象类必须重写基类抽象方法的原因吧!