2016-04-19 12 views
7

tôi đã viết các đoạn mã sau:Polymorphism không hoạt động trong đối số phương pháp trong Java

class Plane {} 
class Airbus extends Plane {} 

public class Main { 

    void fly(Plane p) { 
     System.out.println("I'm in a plane"); 
    } 

    void fly(Airbus a) { 
     System.out.println("I'm in the best Airbus!"); 
    } 

    public static void main(String[] args) { 

     Main m = new Main(); 

     Plane plane = new Plane(); 
     m.fly(plane); 

     Airbus airbus = new Airbus(); 
     m.fly(airbus); 

     Plane planeAirbus = new Airbus(); 
     m.fly(planeAirbus); 

    } 
} 

Và kết quả là:

I'm in a plane 
I'm in the best Airbus! 
I'm in a plane 

gì đáng ngạc nhiên cả hai lời gọi đầu tiên cung cấp cho I'm in a planeI'm in the best Airbus! tương ứng .

Plane planeAirbus = new Airbus(); 

Phương pháp xử lý đối tượng này làm Máy bay, mặc dù đối tượng thực là Airbus. Ngay cả khi tôi thêm abstract-class Plane, có gì thay đổi và kết quả của sự thỉnh nguyện cuối cùng vẫn I'm in a plane

Vì vậy, câu hỏi là tại sao đa hình không hoạt động trong đối số phương pháp và lời gọi là? Có mục đích gì không? Làm thế nào nó hoạt động?

Trả lời

4

Vấn đề ở đây là Java không hỗ trợ ràng buộc động của các đối số phương thức. Những gì bạn thấy là ràng buộc tĩnh, tức là quá tải của phương thức gọi được chọn tại thời gian biên dịch.

Xem thêm: Static Binding and Dynamic Binding

+0

Là tên khác cho động ràng buộc một công văn đôi hay có những khái niệm khác nhau? –

+1

Tôi nghĩ rằng công văn đôi là khác nhau, nhưng công văn đôi thường cũng thực hiện ràng buộc năng động, vì vậy chúng thường được nhìn thấy cùng nhau. – markspace

+1

Công văn đôi có thể được thực hiện trong Java bằng cách sử dụng mẫu Khách truy cập, cần thiết vì Java là một ngôn ngữ được nhập tĩnh. – Timmos

1

Lý do các kết quả sau đầu ra:

I'm in a plane 
I'm in the best Airbus! 
I'm in a plane 

Bởi vì nó được thực hiện quá tải và quá tải là đa hình tĩnh hoặc Compile Time Polymorhism. Trong quá tải, lớp có thể có nhiều hơn một phương thức có cùng tên nhưng các kiểu đối số khác nhau. Trong ví dụ của bạn Plane là loại cho Plane planeAirbus = new Airbus();

2

Phương thức đa hình kiểu quá tải được xác định tại thời gian biên dịch trong Java.

Có nghĩa là Java phải suy ra loại tham số phương thức từ kiểu tham chiếu mà chúng đại diện, vì nó không có ý tưởng về loại đối tượng mà chúng giữ trong thời gian biên dịch.

Chúng tôi có thể cho rằng nó khá rõ ràng trong trường hợp này tham chiếu về loại máy bay nắm giữ thể loại kiểu Airbus. Tuy nhiên nó không đơn giản như vậy, vì bản thân Airbus có thể là một tham số phương thức, nó có thể chứa bất kỳ cá thể lớp con hoặc cá thể Airbus nào.

Chỉ đặt cược an toàn là không phân tích cú pháp thông qua chuỗi gốc và lấy tham chiếu cho giá trị khuôn mặt của nó là loại biến tham chiếu thực tế. Một cách khác để làm điều này có thể có được bằng cách thực hiện phương thức nạp chồng tương tự như ghi đè và bằng cách sử dụng thời gian chạy ràng buộc của các đối tượng để giải quyết. Tôi không biết tại sao nó không được thực hiện theo cách này vì nó đã có thể làm cho phương pháp quá tải và ghi đè thống nhất hơn.

Sau đây là các tài liệu tham khảo từ JLS Overloading

Khi một phương pháp được gọi (§15.12), số lượng các đối số thực tế (và bất kỳ đối số kiểu tường minh) và các loại thời gian biên dịch của các đối số được sử dụng, tại biên dịch thời gian, để xác định chữ ký của phương thức sẽ được viện dẫn (§15.12.2). Nếu phương thức được gọi là phương thức cá thể, phương thức thực tế được gọi sẽ được xác định tại thời gian chạy, sử dụng tra cứu phương thức động (§15.12.4).
1

Quá tải Java là tính đa hình thời gian biên dịch.Vì vậy, khi bạn khai báo planeAirbusPlane, nó sẽ gọi fly(Plane).

Thực tế, lớp học Main không nên biết hơn PlaneAirbus có thể bay. thiết kế tốt hơn của nó:

public interface Flyable{ 
    void fly(); 
} 

public Plane implements Flyable{ 
    void fly(){ 
    //do something 
    } 
} 

public Airbus implements Flyable{ 
    void fly(){ 
     //do something 
    } 
} 

Và sau đó trong Main lớp

public static void main(String[] args) { 
    Flyable plane = new Plane(); 
    plane.fly(plane); 

    Flyable airbus = new Airbus(); 
    airbus.fly(airbus); 
} 
Các vấn đề liên quan