1. Nhưng đó không phải là tất cả.

Giả sử Cowlớp có một printAll()phương thức gọi hai phương thức khác. Sau đó, mã sẽ hoạt động như thế này:

Mã số Sự miêu tả
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor ()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.println("I'm a whale");
   }
}
public static void main(String[] args)
{
   Whale whale = new Whale ();
   whale.printAll();
}
Đầu ra màn hình sẽ là:
I'm a white whale
I'm a whale

Lưu ý rằng khi printAll()phương thức trong Cowlớp được gọi trên một Whaleđối tượng, printNamephương thức củaWhale lớp được sử dụng chứ không phải phương thức trong Cowphương thức.

Điều chính không phải là lớp mà phương thức được viết vào, mà là loại (lớp) của đối tượng mà phương thức được gọi.

Chỉ các phương thức không tĩnh mới có thể được kế thừa và ghi đè. Các phương thức tĩnh không được kế thừa và do đó không thể bị ghi đè.

Đây là Whalegiao diện của lớp sau khi áp dụng kế thừa và ghi đè phương thức:

class Whale
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a whale");
   }
}
Đây là Whalegiao diện của lớp sau khi áp dụng thừa kế và ghi đè phương thức: Chúng tôi không biết về bất kỳ printNamephương thức cũ nào.

2. Đánh máy

Có một điểm thậm chí còn thú vị hơn ở đây. Bởi vì một lớp kế thừa tất cả các phương thức và dữ liệu của lớp cha của nó, nên một tham chiếu đến một đối tượng của lớp con có thể được lưu trữ trong (được gán cho) các biến có kiểu giống với lớp cha (và cha của cha, v.v. — suốt quãng đường lên Objectlớp). Ví dụ:

Mã số Sự miêu tả
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printColor();
}
Đầu ra màn hình sẽ là:
I'm a white whale
public static void main(String[] args)
{
   Cow cow = new Whale();
   cow.printColor();
}
Đầu ra màn hình sẽ là:
I'm a white whale
public static void main(String[] args)
{
   Object o = new Whale();
   System.out.println(o.toString());
}
Đầu ra màn hình sẽ là:
Whale@da435a.

Phương toString()thức được kế thừa từ Objectlớp

Đây là một tài sản rất có giá trị: một lát sau bạn sẽ hiểu cách sử dụng nó trong thực tế.


3. Gọi phương thức trên đối tượng

Khi một phương thức được gọi trên một biến, phương thức đó thực sự được gọi trên một đối tượng. Cơ chế này được gọi là gửi phương thức động.

Đây là giao diện của nó:

Mã số Sự miêu tả
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printName();
}
Đầu ra màn hình sẽ là:
I'm a whale
public static void main(String[] args)
{
   Cow cow = new Whale();
   cow.printName();
}
Đầu ra màn hình sẽ là:
I'm a whale

Lưu ý rằng cách triển khai cụ thể của printName()phương thức được gọi — phương thức trong lớp Cowhoặc phương thức trong lớp Whalekhông được xác định bởi loại biến, mà bởi loại đối tượng mà biến tham chiếu tới.

Biến Cowlưu trữ một tham chiếu đến một Whaleđối tượng và printName()phương thức được định nghĩa trong Whalelớp là phương thức được gọi.

Điều này không rõ ràng lắm. Hãy nhớ quy tắc chính:

Tập hợp các phương thức có sẵn để được gọi trên một biến được xác định bởi loại của biến. Và việc triển khai phương thức cụ thể được gọi được xác định bởi loại/lớp của đối tượng được tham chiếu bởi biến.

Bạn sẽ gặp phải điều này mọi lúc, vì vậy bạn nhớ điều này càng sớm thì càng tốt.