多态(polymorphism)是个大词,可以分解为强调数量丰富的“多”和形态的“态”两部分。所以这个词本质上就是指有许多种形态。在Java中,多态意味着根据object的类型,不同的method会在程序运行时被动态选择调用。

这很像一种小朋友玩的玩具,上面有带有动物名称和图像的转盘以及可以旋转的指针。当指针停下来以后,玩具会发出对应动物的叫声。

在Java程序中的类比是你可以创建class Animal,带上abstractmakeNoise method。每个Animal的子类都可以重写makeNoise来发出每种动物自己的叫声。这被称作基于继承的多态。具有共同parent class的child class可以有自己独有的特性。

Java中的每个object都有声明类型(或编译时类型)以及实际类型(或运行时类型)。顾名思义,前者在object声明时被决定,而后者则由实际创建object的class来决定。

如下所示的nameList的声明类型为List,而实际类型则为ArrayList。Java编译器会检查声明类型是否拥有或者继承了用到的method,否则在找不到的情况下会报错。interface List的确有add method,因而代码可以通过编译。在程序运行时,所执行的add method则由class ArrayList来具体提供,因为它是实际类型。如果在child class里找不到方法的实现,则会一直延继承树上溯。

List<String> nameList = new ArrayList<String>();
nameList.add("Hi");

变量messageObject的声明类型和String的实际类型。执行message.indexOf("h");时会报错,因为indexOf()并非Object的method。

Object message = new String("hi");
message.indexOf("h");

任何对象变量都可以存放声明类型或者声明类型的child class所实例化的object。但是在用()强制转换对象类型前,仅能调用声明类型本身拥有的method。



0:00

What is the output from running the main method in the Shape class?\

public class Shape {
   public void what() { System.out.print("Shape");}

   public static void main(String[] args) {

      Shape[] shapes = {new Shape(), new Rectangle(), new Square(),
                        new Circle()};
      for (Shape s : shapes)
      {
         s.what();
         System.out.print(" ");
      }
   }

}

class Rectangle extends Shape {
   public void what() { System.out.print("Rectangle"); }
}

class Square extends Rectangle {
}

class Oval extends Shape {
   public void what() { System.out.print("Oval"); }
}

class Circle extends Oval {
   public void what() { System.out.print("Circle");}
}
注意Sqaure直接继承了Rectangle,并没有重写what method。
4

What is the output from running the main method in the GradStudent class?

public class Student {

   public String getFood() {
      return "Pizza";
   }

   public String getInfo()  {
     return this.getFood();
   }

   public static void main(String[] args)
   {
     Student s1 = new GradStudent();
     s1.getInfo();
   }
}

class GradStudent extends Student {

  public String getFood() {
     return "Taco";
  }

}
注意getInfo()中调用的getFood()GradStudent中的。
2

What is the output from running the main method in the RaceCar class?

public class Car
{
  private int fuel;

  public Car() { fuel = 0; }
  public Car(int g) { fuel = g; }

  public void addFuel() { fuel++; }
  public void display() { System.out.print(fuel + " "); }

  public static void main(String[] args)
  {
     Car car = new Car(5);
     Car fastCar = new RaceCar(5);
     car.display();
     car.addFuel();
     car.display();
     fastCar.display();
     fastCar.addFuel();
     fastCar.display();
  }

}

class RaceCar extends Car
{
  public RaceCar(int g) { super(2*g); }
}
RaceCar重写了构造函数,让初始燃料变成了原来的两倍。
1

Given the following class definitions and a declaration of Book b = new Dictionary(); which of the following will cause a compile-time error?

public class Book
{
   public String getISBN()
   {
      // implementation not shown
   }

   // constructors, fields, and other methods not shown
}

public class Dictionary extends Book
{
   public String getDefinition(String word)
   {
      // implementation not shown
   }
}
Book中没有getDefintion() method,因而b不能直接调用它。
2

Assume that the following declaration appears in a client program Base b = new Derived();. What is the result of the call b.methodOne()?

public class Base
{
   public void methodOne()
   {
      System.out.print("A");
      methodTwo();
   }

   public void methodTwo()
   {
      System.out.print("B");
   }

   public static void main(String[] args)
   {
      Base b = new Derived();
      b.methodOne();
   }
}

class Derived extends Base
{
   public void methodOne()
   {
      super.methodOne();
      System.out.print("C");
   }

   public void methodTwo()
   {
      super.methodTwo();
      System.out.print("D");
   }
}
super.methodOne()中调用的methodTwo()会是Derived中定义的。
1


陈 欣

AADPS创始人

发表评论