JavaRush /Blog Java /Random-VI /Cơ chế ghi đè phương thức hay Override trong Java

Cơ chế ghi đè phương thức hay Override trong Java

Xuất bản trong nhóm
Xin chào! Bạn đã sử dụng các phương thức trong Java và biết nhiều về chúng. Có thể bạn đã từng gặp phải tình huống có nhiều phương thức trong một lớp có cùng tên nhưng có các đối số khác nhau. Nếu bạn còn nhớ, trong những trường hợp đó chúng ta đã sử dụng cơ chế nạp chồng phương thức. Hôm nay chúng ta hãy xem xét một tình huống khác. Hãy tưởng tượng rằng chúng ta có một phương thức chung, nhưng nó sẽ thực hiện những việc khác nhau tùy thuộc vào lớp mà nó được gọi. Làm thế nào để thực hiện hành vi này? Để tìm ra điều đó, chúng ta hãy lấy một lớp cha Animalbiểu thị động vật và tạo một phương thức trong đó voice- “ voice ”:
public class Animal {

   public void voice() {

       System.out.println("Voice!");
   }
}
Mặc dù chúng tôi mới bắt đầu viết chương trình nhưng rất có thể bạn có thể thấy vấn đề tiềm ẩn: có rất nhiều loài động vật trên thế giới và tất cả chúng đều “nói” khác nhau: mèo kêu, vịt kêu, rắn rít. Cơ chế ghi đè phương thức hoạt động như thế nào - 2 Mục tiêu của chúng tôi rất đơn giản: tránh tạo ra nhiều phương pháp để bỏ phiếu. Thay vì tạo ra các phương thức voiceCat()kêu meo meo, voiceSnake()rít lên, v.v., chúng ta muốn voice()con rắn rít lên, con mèo kêu meo meo và con chó sủa khi phương thức này được gọi. Chúng ta có thể dễ dàng đạt được điều này bằng cách sử dụng cơ chế ghi đè phương thức (Override in Java) . Wikipedia đưa ra lời giải thích sau đây về thuật ngữ "ghi đè": Ghi đè phương thức trong lập trình hướng đối tượng là một trong những tính năng của ngôn ngữ lập trình cho phép một lớp con hoặc lớp con cung cấp cách triển khai cụ thể của một phương thức đã được triển khai trong một trong các siêu lớp hoặc các lớp cha. Nói chung là đúng. Việc ghi đè cho phép bạn lấy một phương thức của lớp cha và viết cách triển khai phương thức này của riêng bạn trong mỗi lớp con. Việc triển khai mới sẽ "thay thế" lớp cha trong lớp con. Hãy xem điều này trông như thế nào bằng một ví dụ. Hãy tạo 4 lớp kế thừa cho lớp của chúng ta Animal:
public class Bear extends Animal {
   @Override
   public void voice() {
       System.out.println("Р-р-р!");
   }
}
public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void voice() {
       System.out.println("Woof!");
   }
}


public class Snake extends Animal {

   @Override
   public void voice() {
       System.out.println("Ш-ш-ш!");
   }
}
Một thủ thuật nhỏ cho tương lai: để ghi đè các phương thức của lớp cha, hãy đi tới mã của lớp con trong Intellij IDE a, nhấn Ctrl+O và chọn “ Ghi đè các phương thức… ” từ menu. Hãy làm quen với việc sử dụng phím nóng ngay từ đầu, nó sẽ tăng tốc độ viết chương trình! Để thiết lập hành vi mong muốn, chúng tôi đã thực hiện một số điều:
  1. Chúng ta đã tạo một phương thức trong mỗi lớp con có cùng tên với phương thức trong lớp cha.
  2. Chúng tôi đã nói với trình biên dịch rằng chúng tôi đặt tên phương thức này giống như trong lớp cha vì một lý do: chúng tôi muốn ghi đè hành vi của nó. Đối với “thông báo” này tới trình biên dịch, chúng tôi đặt chú thích @Override trên phương thức .
    Chú thích @Override được đặt phía trên một phương thức sẽ báo cho trình biên dịch (và các lập trình viên cũng đọc mã của bạn): “Mọi thứ đều ổn, đây không phải là lỗi hay sự quên lãng của tôi. Tôi nhớ rằng phương pháp như vậy đã tồn tại và tôi muốn ghi đè nó."

  3. Chúng tôi đã viết phần triển khai cần thiết cho từng lớp con. Khi được gọi, rắn voice()phải rít lên, gấu phải gầm gừ, v.v.
Hãy xem điều này sẽ hoạt động như thế nào trong chương trình:
public class Main {

   public static void main(String[] args) {

       Animal animal1 = new Dog();
       Animal animal2 = new Cat();
       Animal animal3 = new Bear();
       Animal animal4 = new Snake();

       animal1.voice();
       animal2.voice();
       animal3.voice();
       animal4.voice();
   }
}
Đầu ra của bảng điều khiển: Gâu! Meo! Rrrr! Suỵt! Tuyệt vời, mọi thứ đều hoạt động như bình thường! Chúng ta đã tạo 4 biến tham chiếu của lớp cha Animalvà gán chúng cho 4 đối tượng khác nhau của lớp con. Kết quả là mỗi đối tượng hoạt động khác nhau. Đối với mỗi lớp con, phương thức được ghi đè voice()đã thay thế phương thức “gốc” voice()từ lớp đó Animal(phương thức này chỉ xuất ra “Voice!” cho bảng điều khiển). Cơ chế ghi đè phương thức hoạt động như thế nào - 3 Việc ghi đè có một số hạn chế:
  1. Phương thức được ghi đè phải có cùng đối số với phương thức gốc.

    Nếu một phương thức voicetrong lớp cha chấp nhận là đầu vào Stringthì phương thức được ghi đè trong lớp con cũng phải chấp nhận là đầu vào String, nếu không trình biên dịch sẽ đưa ra lỗi:

    public class Animal {
    
       public void voice(String s) {
    
           System.out.println("Voice! " + s);
       }
    }
    
    public class Cat extends Animal {
    
       @Override//error!
       public void voice() {
           System.out.println("Meow!");
       }
    }

  2. Phương thức được ghi đè phải có cùng kiểu trả về với phương thức gốc.

    Nếu không, chúng ta sẽ nhận được lỗi biên dịch:

    public class Animal {
    
       public void voice() {
    
           System.out.println("Voice!");
       }
    }
    
    
    public class Cat extends Animal {
    
       @Override
       public String voice() {         //error!
           System.out.println("Meow!");
           return "Meow!";
       }
    }

  3. Công cụ sửa đổi quyền truy cập của một phương thức bị ghi đè cũng không thể khác với phương thức “gốc”:

    public class Animal {
    
       public void voice() {
    
           System.out.println("Voice!");
       }
    }
    
    public class Cat extends Animal {
    
       @Override
       private void voice() {      //error!
           System.out.println("Meow!");
       }
    }
Ghi đè phương thức trong Java là một trong những công cụ để triển khai ý tưởng về tính đa hình (nguyên tắc của OOP, mà chúng ta đã nói đến trong bài giảng trước). Do đó, ưu điểm chính của việc sử dụng nó sẽ là tính linh hoạt giống như chúng ta đã nói trước đó. Chúng ta có thể xây dựng một hệ thống các lớp đơn giản và hợp lý, mỗi lớp sẽ có hành vi cụ thể (chó sủa, mèo kêu), nhưng với một giao diện duy nhất - một phương thức voice()cho tất cả thay vì một loạt các phương thức voiceDog(), voiceCat()v.v.
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION