Cách quá tải phương thức trong java

Quá tải phương thức có thể đạt được theo ba cách sau -

  • Bằng cách thay đổi số lượng tham số trong phương thức
  • Bằng cách thay đổi thứ tự của các loại tham số
  • Bằng cách thay đổi kiểu dữ liệu của các tham số

Xem ví dụ bên dưới−

Thí dụ

Bản thử trực tiếp

public class Tester {
   public static void main[String args[]] {
      Tester tester = new Tester[];
      System.out.println[tester.add[1, 2]];
      System.out.println[tester.add[1, 2,3]];
      System.out.println[tester.add[1.0f, 2,3]];
      System.out.println[tester.add[1, 2.0f,3]];
   }
   public int add[int a, int b] {
      return a + b;
   }
   public int add[int a, int b, int c] {
      return a + b + c;
   }
   public float add[float a, int b, int c] {
      return a + b + c;
   }
   public float add[int a, float b, int c] {
      return a + b + c;
   }
}

đầu ra

3
6
6.0
6.0

Nạp chồng và ghi đè phương thức là những khái niệm chính của ngôn ngữ lập trình Java và do đó, chúng xứng đáng được xem xét chuyên sâu

Trong bài viết này, chúng ta sẽ tìm hiểu kiến ​​thức cơ bản của những khái niệm này và xem chúng có thể hữu ích trong những tình huống nào

2. Quá tải phương thức

Nạp chồng phương thức là một cơ chế mạnh mẽ cho phép chúng ta định nghĩa các API lớp gắn kết. Để hiểu rõ hơn tại sao nạp chồng phương thức lại là một tính năng có giá trị như vậy, hãy xem một ví dụ đơn giản

Giả sử rằng chúng ta đã viết một lớp tiện ích ngây thơ thực hiện các phương thức khác nhau để nhân hai số, ba số, v.v.

Nếu chúng ta đã đặt cho các phương thức những cái tên gây nhầm lẫn hoặc mơ hồ, chẳng hạn nhưmultiple2[],multiple3[],multiply4[], thì đó sẽ là một lớp API được thiết kế tồi. Đây là nơi quá tải phương thức phát huy tác dụng

Nói một cách đơn giản, chúng ta có thể thực hiện nạp chồng phương thức theo hai cách khác nhau

  • thực hiện hai hoặc nhiều phương thức có cùng tên nhưng có số lượng đối số khác nhau
  • thực hiện hai hoặc nhiều phương thức có cùng tên nhưng lấy các đối số thuộc các loại khác nhau

2. 1. Số đối số khác nhau

Tóm lại, lớp Multiplier chỉ ra cách quá tải phương thức multiplier bằng cách chỉ định nghĩa hai triển khai nhận số lượng đối số khác nhau

public class Multiplier {
    
    public int multiply[int a, int b] {
        return a * b;
    }
    
    public int multiply[int a, int b, int c] {
        return a * b * c;
    }
}

2. 2. Đối số của các loại khác nhau

Tương tự, chúng ta có thể quá tải phương thức multi[] bằng cách làm cho nó chấp nhận các đối số thuộc các kiểu khác nhau.

public class Multiplier {
    
    public int multiply[int a, int b] {
        return a * b;
    }
    
    public double multiply[double a, double b] {
        return a * b;
    }
}

Hơn nữa, việc định nghĩa lớp Multiplier với cả hai loại nạp chồng phương thức là hợp pháp.

public class Multiplier {
    
    public int multiply[int a, int b] {
        return a * b;
    }
    
    public int multiply[int a, int b, int c] {
        return a * b * c;
    }
    
    public double multiply[double a, double b] {
        return a * b;
    }
}

Tuy nhiên, điều đáng chú ý là không thể có hai cách triển khai phương thức chỉ khác nhau về kiểu trả về của chúng

Để hiểu tại sao – hãy xem xét ví dụ sau

public int multiply[int a, int b] { 
    return a * b; 
}
 
public double multiply[int a, int b] { 
    return a * b; 
}

Trong trường hợp này, mã đơn giản là sẽ không biên dịch được do cách gọi phương thức không rõ ràng – trình biên dịch sẽ không biết cách triển khai hàm multi[] nào để gọi

2. 3. Loại Khuyến mãi

Một tính năng thú vị được cung cấp bởi quá tải phương thức là cái gọi là khuyến mãi kiểu, một. k. a. mở rộng chuyển đổi ban đầu .

Nói một cách đơn giản, một loại đã cho được thăng cấp hoàn toàn cho một loại khác khi không có sự khớp giữa các loại đối số được truyền cho phương thức quá tải và triển khai phương thức cụ thể

Để hiểu rõ hơn về cách hoạt động của khuyến mãi kiểu, hãy xem xét các triển khai sau đây của phương thức multi[]

public double multiply[int a, long b] {
    return a * b;
}

public int multiply[int a, int b, int c] {
    return a * b * c;
}

Bây giờ, gọi phương thức với hai đối số int sẽ dẫn đến đối số thứ hai được thăng cấp thành long, vì trong trường hợp này không có triển khai phù hợp của phương thức với hai đối số int

Hãy xem thử nghiệm đơn vị nhanh để chứng minh loại quảng cáo

@Test
public void whenCalledMultiplyAndNoMatching_thenTypePromotion[] {
    assertThat[multiplier.multiply[10, 10]].isEqualTo[100.0];
}

Ngược lại, nếu chúng ta gọi phương thức có triển khai phù hợp, thì việc khuyến mãi kiểu sẽ không diễn ra

________số 8

Dưới đây là tóm tắt các quy tắc khuyến mãi loại áp dụng cho quá tải phương thức

  • byte có thể được thăng cấp thành short, int, long, float hoặc double
  • short có thể được thăng cấp thành int, long, float hoặc double
  • char có thể được thăng cấp thành int, long, float hoặc double
  • int có thể được thăng cấp thành long, float hoặc double
  • long có thể được thăng cấp lên float hoặc double
  • float có thể được tăng gấp đôi

2. 4. Liên kết tĩnh

Khả năng liên kết một lệnh gọi phương thức cụ thể với phần thân của phương thức được gọi là liên kết

Trong trường hợp nạp chồng phương thức, liên kết được thực hiện tĩnh tại thời điểm biên dịch, do đó nó được gọi là liên kết tĩnh

Trình biên dịch có thể đặt ràng buộc một cách hiệu quả tại thời điểm biên dịch bằng cách kiểm tra chữ ký của các phương thức

3. Ghi đè phương thức

Ghi đè phương thức cho phép chúng tôi cung cấp các triển khai chi tiết trong các lớp con cho các phương thức được định nghĩa trong lớp cơ sở

Mặc dù ghi đè phương thức là một tính năng mạnh mẽ - coi đó là hệ quả hợp lý của việc sử dụng tính kế thừa, một trong những trụ cột lớn nhất của OOP - nên phân tích cẩn thận khi nào và ở đâu để sử dụng nó, trên cơ sở từng trường hợp sử dụng

Bây giờ chúng ta hãy xem cách sử dụng ghi đè phương thức bằng cách tạo mối quan hệ [“is-a”] đơn giản, dựa trên sự kế thừa

Đây là lớp cơ sở

public class Vehicle {
    
    public String accelerate[long mph] {
        return "The vehicle accelerates at : " + mph + " MPH.";
    }
    
    public String stop[] {
        return "The vehicle has stopped.";
    }
    
    public String run[] {
        return "The vehicle is running.";
    }
}

Và đây là một phân lớp giả tạo

3
6
6.0
6.0
0

Trong hệ thống phân cấp ở trên, chúng tôi chỉ đơn giản ghi đè phương thức gia tốc [] để cung cấp cách triển khai tinh tế hơn cho kiểu con Xe hơi

Ở đây, rõ ràng là nếu một ứng dụng sử dụng các thể hiện của lớp Xe, thì nó cũng có thể hoạt động với các thể hiện của Xe, vì cả hai cách triển khai của phương thức Accel[] đều có cùng một chữ ký và cùng một kiểu trả về.

Hãy viết một vài bài kiểm tra đơn vị để kiểm tra các lớp Vehicle và Car

3
6
6.0
6.0
1

Bây giờ, hãy xem một số bài kiểm tra đơn vị cho biết cách các phương thức run[] và stop[], không bị ghi đè, trả về các giá trị bằng nhau cho cả Ô tô và Xe cộ

public class Multiplier {
    
    public int multiply[int a, int b] {
        return a * b;
    }
    
    public double multiply[double a, double b] {
        return a * b;
    }
}
0

Trong trường hợp của chúng ta, chúng ta có quyền truy cập vào mã nguồn của cả hai lớp, vì vậy chúng ta có thể thấy rõ ràng rằng việc gọi phương thức express[] trên một thể hiện Xe cơ sở và gọi phương thức express[] trên một thể hiện Xe sẽ trả về các giá trị khác nhau cho cùng một đối số

Do đó, thử nghiệm sau đây chứng minh rằng phương thức bị ghi đè được gọi cho một phiên bản Car

public class Multiplier {
    
    public int multiply[int a, int b] {
        return a * b;
    }
    
    public double multiply[double a, double b] {
        return a * b;
    }
}
1

3. 1. Loại khả năng thay thế

Một nguyên tắc cốt lõi trong OOP là khả năng thay thế kiểu, được liên kết chặt chẽ với Nguyên tắc thay thế Liskov [LSP]

Nói một cách đơn giản, LSP tuyên bố rằng nếu một ứng dụng hoạt động với một kiểu cơ sở nhất định, thì nó cũng sẽ hoạt động với bất kỳ kiểu con nào của nó. Bằng cách đó, khả năng thay thế loại được bảo toàn đúng cách

Vấn đề lớn nhất với ghi đè phương thức là một số triển khai phương thức cụ thể trong các lớp dẫn xuất có thể không hoàn toàn tuân theo LSP và do đó không duy trì được khả năng thay thế kiểu

Tất nhiên, việc tạo một phương thức bị ghi đè để chấp nhận các đối số thuộc các loại khác nhau và trả về một loại khác là hợp lệ, nhưng phải tuân thủ đầy đủ các quy tắc này

  • Nếu một phương thức trong lớp cơ sở nhận [các] đối số của một loại nhất định, thì phương thức được ghi đè sẽ lấy cùng loại hoặc siêu kiểu [a. k. a. đối số phương pháp chống biến]
  • Nếu một phương thức trong lớp cơ sở trả về void, phương thức bị ghi đè sẽ trả về void
  • Nếu một phương thức trong lớp cơ sở trả về một phương thức nguyên thủy, thì phương thức được ghi đè sẽ trả về cùng một phương thức nguyên thủy
  • Nếu một phương thức trong lớp cơ sở trả về một kiểu nhất định, thì phương thức được ghi đè sẽ trả về cùng một kiểu hoặc một kiểu con [a. k. a. kiểu trả về hiệp biến]
  • Nếu một phương thức trong lớp cơ sở đưa ra một ngoại lệ, thì phương thức được ghi đè phải đưa ra cùng một ngoại lệ hoặc một kiểu con của ngoại lệ lớp cơ sở

3. 2. Liên kết động

Xem xét rằng việc ghi đè phương thức chỉ có thể được thực hiện với tính kế thừa, trong đó có một hệ thống phân cấp của loại cơ sở và [các] loại con, trình biên dịch không thể xác định tại thời điểm biên dịch nên gọi phương thức nào, vì cả lớp cơ sở và lớp con đều xác định

Do đó, trình biên dịch cần kiểm tra loại đối tượng để biết phương thức nào sẽ được gọi

Vì việc kiểm tra này xảy ra trong thời gian chạy, ghi đè phương thức là một ví dụ điển hình của liên kết động

4. Sự kết luận

Trong hướng dẫn này, chúng ta đã học cách triển khai nạp chồng phương thức và ghi đè phương thức, đồng thời khám phá một số tình huống điển hình mà chúng hữu ích

Làm cách nào để quá tải phương thức chính trong Java?

Làm cách nào chúng tôi có thể gọi Phương thức main[] đã quá tải? . Vì vậy, để gọi các phương thức main[] bị quá tải, chúng ta cần phải gọi nó từ phương thức main[] ban đầu .

Chúng ta có thể quá tải các phương thức trong Java không?

Trong Java, hai hoặc nhiều phương thức có thể có cùng tên nếu chúng khác nhau về tham số [số lượng tham số khác nhau, loại tham số khác nhau hoặc cả hai]. Các phương thức này được gọi là phương thức quá tải và tính năng này được gọi là nạp chồng phương thức

Làm cách nào tôi có thể chạy một phương thức bị quá tải?

Để gọi phương thức main[] bị quá tải, chúng ta phải gọi nó từ phương thức main[] ban đầu. Hãy hiểu nó thông qua một ví dụ. Trong ví dụ trên, có hai phương thức main[]. Phương thức main[] đầu tiên là phương thức gốc và phương thức main[] thứ hai là phương thức main[] quá tải

Chủ Đề