什么叫多态?我们先来谈谈继承。在面向对象的编程中,继承是一种常用的技术。假设有一个类Shap,Shap有两个方法,即draw()和erase()。Circle也是一种特殊Shap,所以只需要使用继承的方法,使用class CricleextendsShap语句就可以创建一个新类Circle。Circle类具有Shap类的全部特征,包括所有的方法。这里只介绍了继承,到底这和多态有什么关系,到底什么又叫多态呢?看下面的语句:
class Shap {
void draw(){
System.out.println("Shap.draw()");
}
void erase(){
System.out.println("Shap.erase()");
}
}
class Circle extends Shap{
void draw(){
System.out.println("Circle.draw()");
}
void erase(){
System.out.println("Circle.erase()");
}
}
class Square extends Shap{
void draw(){
System.out.println("Square.draw()");
}
void erase(){
System.out.println("Square.erase()");
}
}
public class Picture{
void add(Shap s){
s.draw();
}
public static void main(String[] args) {
Picture p=new Picture();
Shap[] e={
new Circle(),
new Square()
};
for(int i=0;i<e.length;i++)
p.add(e[i]);
}
}
注意看上面加红色的语句,及void add(Shap s){s.draw();}这表示一个Picture类的一个方法要使用Shap类作为形式参数并调用该参数的draw()方法。我们在接下来的语句中看到,不管你的Shap类的子类是Circle还是Square,在传递给方法add()后,add()能自动判断是调用Circle的draw()方法还是Square的draw()方法。JAVA这种“后期绑定”的本领就叫做多态。可以看出,你不必专门为Circle类写一个add()方法,再为Square写一个add()方法,只需要为它们的基类写一个方法,剩下的编译器就能为你自动选择你想要调用的正确的方法。如果多态仅仅是一种“向上转型”的形式的话,我们得到的仅仅是节省了一点代码的话,也许我们不必要给予太多的关注,那多态到底有什么其它好处呢?在上面的例子中新加一个Line类,它也继承了Shap类,如下所示:
class Shap {
void draw(){
System.out.println("Shap.draw()");
}
void erase(){
System.out.println("Shap.erase()");
}
}
class Circle extends Shap{
void draw(){
System.out.println("Circle.draw()");
}
void erase(){
System.out.println("Circle.erase()");
}
}
class Square extends Shap{
void draw(){
System.out.println("Square.draw()");
}
void erase(){
System.out.println("Square.erase()");
}
}
class Line extends Shap{
void draw(){
System.out.println("Line.draw()");
}
void erase(){
System.out.println("Line.erase()");
}
}
public class Picture{
void add(Shap s){
s.draw();
}
public static void main(String[] args) {
Picture p=new Picture();
Shap[] e={
new Circle(),
new Square(),
new Line()
};
for(int i=0;i<e.length;i++)
p.add(e[i]);
}
}
可以看出add()方法根本不必要知道有新类的增加而继续正常工作。咋看,这只不过还是节省了几行代码的问题,你可以为每个子类都写一个add()方法,同样能解决问题。有新类的加入时再为这个新类写add()方法。这不仅仅是节省了几行代码,多敲几行代码并不会如何提高编码的效率。这是一个思想,你根本不用关心基类今天多了一个子类,明天又多了一个子类,不用担心的你的代码中,对于新加入的子类能否正常的运行,因为你直接与基类的接口进行通信,避免了复杂性。换句话说,你的代码具有很好的可扩展性,基类可以随时根据需要进行扩展而不用担心代码的运行问题。
final关键字:
可以在三种情况下使用final,及final数据,final方法,final类
1.final数据。final修饰的数字表示一个永不改变的编译时常量,对这个常量定义时必须对其进行赋值,可以在构造器中对其进行赋值(这种方法又叫空白final)。
用final加static修饰的字段只占据一段不可改变的存储空间。
2.final方法。final方法是把方法锁定,确保在继承中该方法行为保持不变,并且不会被覆盖。
3.fianl类。final修饰的类不能有继承类。