浅谈对Java多态的理解与应用

什么是多态

一般说道多态,也离不开封装与继承。按我的理解,Java中的封装,就是把一些属性与方法打包成一个类,用来描述一个对象的状态与动作。Java中的继承,则是通过继承一个通用类来得到一个一个更具体的类。两者都是能帮助我们更好地进行建模的代码格式。

理解多态的概念也离不开封装与继承。多态的字面意思就是多种形式、多种形态。例如,几何图形可以是圆、三角形、矩形或任意不规则的图形。为了将这种抽象的关系体现在Java上,我们可以先定义一个几何图形的通用类,再通过继承得到圆、三角形这些子类。在使用过程中,不必先定义某一个子类引用,在把一个子类实例传递给它,因为每个子类的实例都是父类的特殊化,因此总是可以将子类的实例传给需要父类型的参数,大大提升了编程的灵活性。

背景知识:封装、继承与方法重写

class Animal {
    public void animalSound() {
        System.out.println("The animal makes a sound");
    }
}

class Pig extends Animal {
    @Override
    public void animalSound() {
        System.out.println("The pig says: wee wee");
    }
}

class Dog extends Animal {
    @Override
    public void animalSound() {
        System.out.println("The dog says: bow wow");
    }
}

知识点详述:多态的应用及类型转换

下面用父类型引用来指向子类型实例

class Animal {
  public void animalSound() {
    System.out.println("The animal makes a sound");
  }
}

class Pig extends Animal {
  public void animalSound() {
    System.out.println("The pig says: wee wee");
  }
  public void display() {
    System.out.println("Pig");
  }
}

class Dog extends Animal {
  public void animalSound() {
    System.out.println("The dog says: bow wow");
  }
}

class Main {
  public static void main(String[] args) {
    Animal myAnimal = new Animal();  // Create a Animal object
    Animal myPig = new Pig();  // Create a Pig object
    Animal myDog = new Dog();  // Create a Dog object
    myAnimal.animalSound();
    myPig.animalSound();
    myDog.animalSound();
    
    //myPig.display(); 编译错误
    
    Pig p = (Pig)myPig;
    p.display();
  }
}

Java中,总是可以将一个子类的实例转换为一个父类的变量,称为向上转换(upcasting)。但要注意转换后的父类引用不能调用子类有而自身没有的方法,像上面的myPig.display()就会出现编译错误。为了解决这一问题,要用到向下转换(downcasting),也就是把父类实例转换为子类变量。这时必须用转换标记“(子类名)”进行显示转换,向编译器表明你的意图,于是就可以调用子类的特殊方法,结果如下

The animal makes a sound
The pig says: wee wee
The dog says: bow wow
Pig

使用场景

下面介绍一个多态的应用场景。假设有三次考试,每次的分数制都不一样,第一次采用五级计分制第二次采用两级计分制,第三次采用五级计分制。若要显示每次考试的成绩,如果采用一般的思路,要对三次考试分别建模,并编写不同的getScore方法,再分别调用。而在Java中,可以让这三次考试都继承自一个通用类(GradeActivity),并分别重写各自的getScore方法,最后用循环依此调用getScore方法,即使test中有上百个实例,每个实例的计分方法都不同,也可以用循环来实现。

public static void main(String[] args) {
    GradedActivity[] tests = new GradedActivity[3];
    // 第一次考试采用五级计分制,考了75
    tests[0] = new GradedActivity();
    tests[0].setScore(75);
    // 第二次考试采用二级计分制(P或者F)。总共20题,每题分值相同,考生答错5题。
    // 通过的最低分数线是60分
    tests[1] = new PassFailExam(20, 5, 60);
    // 第三次是期末考试也采用五级计分制. 总共50题,每题分值相同,考试答错7题
    tests[2] = new FinalExam(50, 7);
    // 显示每次考试的分数和等级
    for(int i=0; i<tests.length; i++){
        showValue(tests[i]);
    }
}
public static void showValue(GradedActivity exam){
    System.out.println("Score: " + exam.getScore()+ "\t" + 
    "Grade: " + exam.getGrade());
}

小结

与其说多态是一种代码格式,不如说多态是一种写代码的技巧。能否利用好多态的机制取决于对需求的理解,如果能利用好其特性,能在实际的应用场景中减轻工作量,提升程序的灵活性。

上一篇:cmd中mvn命令,出现No compiler is provided in this environment. Perhaps you are running on a JRE rather tha


下一篇:报错:java.net.UnknownHostException: iMac: nodename nor servname provided, or not known