JavaRush /Blog Java /Random-VI /Đa hình và những người bạn của nó
Viacheslav
Mức độ

Đa hình và những người bạn của nó

Xuất bản trong nhóm
Đa hình là một trong những nguyên tắc cơ bản của lập trình hướng đối tượng. Nó cho phép bạn khai thác sức mạnh của khả năng gõ mạnh của Java và viết mã có thể sử dụng và bảo trì. Người ta đã nói rất nhiều về anh ấy, nhưng tôi hy vọng mọi người có thể rút ra được điều gì đó mới mẻ từ bài đánh giá này.
Đa hình và những người bạn của nó - 1

Giới thiệu

Tôi nghĩ tất cả chúng ta đều biết rằng ngôn ngữ lập trình Java thuộc về Oracle. Do đó, con đường của chúng tôi bắt đầu từ trang web: www.oracle.com . Có một "Menu" trên trang chính. Trong đó, ở phần “Tài liệu” có một tiểu mục “Java”. Mọi thứ liên quan đến các chức năng cơ bản của ngôn ngữ đều thuộc về "tài liệu Java SE", vì vậy chúng tôi chọn phần này. Phần tài liệu sẽ mở cho phiên bản mới nhất, nhưng hiện tại là phần "Đang tìm bản phát hành khác?" Hãy chọn tùy chọn: JDK8. Trên trang chúng ta sẽ thấy nhiều tùy chọn khác nhau. Nhưng chúng tôi quan tâm đến Học ngôn ngữ: " Lộ trình học tập hướng dẫn Java ". Trên trang này chúng ta sẽ tìm thấy một phần khác: " Học ngôn ngữ Java ". Đây là điều thiêng liêng nhất, một hướng dẫn về Java cơ bản từ Oracle. Java là ngôn ngữ lập trình hướng đối tượng (OOP), vì vậy việc học ngôn ngữ này ngay cả trên trang web của Oracle cũng bắt đầu bằng cuộc thảo luận về các khái niệm cơ bản về “ Khái niệm lập trình hướng đối tượng ”. Ngay từ cái tên, rõ ràng Java tập trung vào làm việc với các đối tượng. Từ tiểu mục " Đối tượng là gì? ", rõ ràng các đối tượng trong Java bao gồm trạng thái và hành vi. Hãy tưởng tượng rằng chúng ta có một tài khoản ngân hàng. Số tiền trong tài khoản là một trạng thái và phương pháp làm việc với trạng thái này là hành vi. Các đối tượng cần được mô tả bằng cách nào đó (cho biết trạng thái và hành vi của chúng) và mô tả này là lớp . Khi chúng ta tạo một đối tượng của một lớp nào đó, chúng ta chỉ định lớp này và lớp này được gọi là “ kiểu đối tượng ”. Do đó, người ta nói rằng Java là một ngôn ngữ được định kiểu mạnh, như đã nêu trong đặc tả ngôn ngữ Java trong phần " Chương 4. Kiểu, Giá trị và Biến ". Ngôn ngữ Java tuân theo các khái niệm OOP và hỗ trợ tính kế thừa bằng từ khóa mở rộng. Tại sao phải mở rộng? Bởi vì với tính kế thừa, lớp con kế thừa hành vi và trạng thái của lớp cha và có thể bổ sung cho chúng, tức là. mở rộng chức năng của lớp cơ sở. Một giao diện cũng có thể được chỉ định trong mô tả lớp bằng từ khóa thực hiện. Khi một lớp thực hiện một giao diện, điều đó có nghĩa là lớp đó tuân theo một hợp đồng nào đó - một tuyên bố của người lập trình với phần còn lại của môi trường rằng lớp đó có một hành vi nhất định. Ví dụ, trình phát có nhiều nút khác nhau. Các nút này là giao diện để điều khiển hoạt động của trình phát và hành vi này sẽ thay đổi trạng thái bên trong của trình phát (ví dụ: âm lượng). Trong trường hợp này, trạng thái và hành vi được mô tả sẽ đưa ra một lớp. Nếu một lớp thực hiện một giao diện, thì một đối tượng được tạo bởi lớp này có thể được mô tả bằng một kiểu không chỉ bởi lớp mà còn bởi giao diện. Hãy xem một ví dụ:
public class MusicPlayer {

    public static interface Device {
        public void turnOn();
        public void turnOff();
    }

    public static class Mp3Player implements Device {
        public void turnOn() {
            System.out.println("On. Ready for mp3.");
        }
        public void turnOff() {
            System.out.println("Off");
        }
    }

    public static class Mp4Player extends Mp3Player {
        @Override
        public void turnOn() {
            System.out.println("On. Ready for mp3/mp4.");
        }
    }

    public static void main(String []args) throws Exception{
        // Какое-то устройство (Тип = Device)
        Device mp3Player = new Mp3Player();
        mp3Player.turnOn();
        // У нас есть mp4 проигрыватель, но нам от него нужно только mp3
        // Пользуемся им How mp3 проигрывателем (Тип = Mp3Player)
        Mp3Player mp4Player = new Mp4Player();
        mp4Player.turnOn();
    }
}
Loại là một mô tả rất quan trọng. Nó cho biết chúng ta sẽ làm việc với đối tượng như thế nào, tức là. hành vi mà chúng ta mong đợi từ đối tượng. Hành vi là phương pháp. Vì vậy, chúng ta hãy hiểu các phương pháp. Trên trang web của Oracle, các phương thức có phần riêng trong Hướng dẫn của Oracle: " Xác định phương thức ". Điều đầu tiên cần rút ra từ bài viết: Chữ ký phương thức là tên của phương thức và các loại tham số :
Đa hình và những người bạn của nó - 2
Ví dụ: khi khai báo một phương thức public void Method(Object o), chữ ký sẽ là tên của phương thức và kiểu của tham số Object. Kiểu trả về KHÔNG được bao gồm trong chữ ký. Nó quan trọng! Tiếp theo, hãy biên dịch mã nguồn của chúng tôi. Như chúng ta đã biết, để làm được điều này, mã phải được lưu trong một tệp có tên lớp và phần mở rộng java. Mã Java được biên dịch bằng trình biên dịch " javac " thành một số định dạng trung gian có thể được thực thi bởi Máy ảo Java (JVM). Định dạng trung gian này được gọi là mã byte và được chứa trong các tệp có phần mở rộng .class. Hãy chạy lệnh để biên dịch: javac MusicPlayer.java Sau khi mã java được biên dịch, chúng ta có thể thực thi nó. Sử dụng tiện ích " java " để khởi động, quy trình máy ảo java sẽ được khởi chạy để thực thi mã byte được truyền trong tệp lớp. Hãy chạy lệnh để khởi chạy ứng dụng: java MusicPlayer. Chúng ta sẽ thấy trên màn hình văn bản được chỉ định trong tham số đầu vào của phương thức println. Điều thú vị là, có mã byte trong một tệp có phần mở rộng .class, chúng ta có thể xem nó bằng tiện ích " javap ". Hãy chạy lệnh <ocde>javap -c MusicPlayer:
Đa hình và những người bạn của nó - 3
Từ mã byte, chúng ta có thể thấy rằng việc gọi một phương thức thông qua một đối tượng có loại lớp được chỉ định được thực hiện bằng cách sử dụng invokevirtualvà trình biên dịch đã tính toán chữ ký phương thức nào sẽ được sử dụng. Tại sao invokevirtual? Bởi vì có một cuộc gọi (gọi được dịch là gọi) của một phương thức ảo. Phương pháp ảo là gì? Đây là một phương thức mà phần thân của nó có thể bị ghi đè trong quá trình thực hiện chương trình. Đơn giản chỉ cần tưởng tượng rằng bạn có một danh sách tương ứng giữa một khóa nhất định (chữ ký phương thức) và phần nội dung (mã) của phương thức. Và sự tương ứng giữa khóa và nội dung của phương thức có thể thay đổi trong quá trình thực hiện chương trình. Do đó phương pháp này là ảo. Theo mặc định, trong Java, các phương thức KHÔNG tĩnh, KHÔNG cuối cùng và KHÔNG riêng tư là ảo. Nhờ đó, Java hỗ trợ nguyên tắc lập trình hướng đối tượng đa hình. Như bạn có thể đã hiểu, đây chính là nội dung bài đánh giá của chúng tôi ngày hôm nay.

Đa hình

Trên trang web của Oracle trong Hướng dẫn chính thức của họ có một phần riêng: " Đa hình ". Hãy sử dụng Trình biên dịch trực tuyến Java để xem tính đa hình hoạt động như thế nào trong Java. Ví dụ: chúng ta có một số lớp trừu tượng Number đại diện cho một số trong Java. Nó cho phép những gì? Anh ta có một số kỹ thuật cơ bản mà tất cả những người thừa kế sẽ có. Bất cứ ai kế thừa Số đều nói theo đúng nghĩa đen - “Tôi là một con số, bạn có thể làm việc với tôi như một con số”. Ví dụ: đối với bất kỳ người kế nhiệm nào, bạn có thể sử dụng phương thức intValue() để lấy giá trị Số nguyên của nó. Nếu nhìn vào api java cho Number, bạn có thể thấy rằng phương thức này là trừu tượng, tức là mỗi người kế thừa của Number phải tự triển khai phương thức này. Nhưng điều này mang lại cho chúng ta điều gì? Hãy xem một ví dụ:
public class HelloWorld {

    public static int summ(Number first, Number second) {
        return first.intValue() + second.intValue();
    }

    public static void main(String []args){
        System.out.println(summ(1, 2));
        System.out.println(summ(1L, 4L));
        System.out.println(summ(1L, 5));
        System.out.println(summ(1.0, 3));
    }
}
Như có thể thấy từ ví dụ, nhờ tính đa hình, chúng ta có thể viết một phương thức sẽ chấp nhận các đối số thuộc bất kỳ loại nào làm đầu vào, sẽ là hậu duệ của Number (chúng ta không thể lấy Number, vì nó là một lớp trừu tượng). Như trường hợp của ví dụ về trình phát, trong trường hợp này, chúng tôi đang nói rằng chúng tôi muốn làm việc với thứ gì đó, chẳng hạn như Number. Chúng tôi biết rằng bất kỳ ai là Số đều phải có khả năng cung cấp giá trị số nguyên của nó. Và thế là đủ đối với chúng tôi. Chúng tôi không muốn đi sâu vào chi tiết việc triển khai một đối tượng cụ thể và muốn làm việc với đối tượng này thông qua các phương thức chung cho tất cả các hậu duệ của Number. Danh sách các phương thức có sẵn cho chúng ta sẽ được xác định theo loại tại thời điểm biên dịch (như chúng ta đã thấy trước đó trong mã byte). Trong trường hợp này, loại của chúng tôi sẽ là Số. Như bạn có thể thấy trong ví dụ, chúng ta đang chuyển các số khác nhau thuộc các loại khác nhau, nghĩa là phương thức summ sẽ nhận Integer, Long và Double làm đầu vào. Nhưng tất cả chúng đều có điểm chung là chúng là hậu duệ của Số trừu tượng và do đó ghi đè hành vi của chúng trong phương thức intValue, bởi vì mỗi loại cụ thể đều biết cách truyền loại đó thành Integer. Tính đa hình như vậy được thực hiện thông qua cái gọi là ghi đè, trong tiếng Anh Ghi đè.
Đa hình và những người bạn của nó - 4
Ghi đè hoặc đa hình động. Vì vậy, chúng ta hãy bắt đầu bằng việc lưu file HelloWorld.java với nội dung sau:
public class HelloWorld {
    public static class Parent {
        public void method() {
            System.out.println("Parent");
        }
    }
    public static class Child extends Parent {
        public void method() {
            System.out.println("Child");
        }
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();
        parent.method();
        child.method();
    }
}
Hãy làm javac HelloWorld.javajavap -c HelloWorld:
Đa hình và những người bạn của nó - 5
Như bạn có thể thấy, trong mã byte cho các dòng có lệnh gọi phương thức, tham chiếu tương tự đến phương thức gọi được chỉ định invokevirtual (#6). Hãy làm nó java HelloWorld. Như chúng ta có thể thấy, các biến cha và con được khai báo bằng kiểu Parent, nhưng bản thân việc triển khai được gọi tùy theo đối tượng nào được gán cho biến (tức là loại đối tượng nào). Trong quá trình thực thi chương trình (họ cũng nói trong thời gian chạy), JVM, tùy thuộc vào đối tượng, khi gọi các phương thức sử dụng cùng một chữ ký, sẽ thực thi các phương thức khác nhau. Nghĩa là, bằng cách sử dụng khóa của chữ ký tương ứng, trước tiên chúng tôi nhận được một nội dung phương thức, sau đó nhận được một nội dung khác. Tùy thuộc vào đối tượng nào có trong biến. Việc xác định tại thời điểm thực hiện chương trình phương thức nào sẽ được gọi còn được gọi là liên kết muộn hoặc Liên kết động. Nghĩa là, việc khớp giữa chữ ký và phần thân phương thức được thực hiện một cách linh hoạt, tùy thuộc vào đối tượng mà phương thức được gọi. Đương nhiên, bạn không thể ghi đè các thành viên tĩnh của một lớp (Thành viên lớp), cũng như các thành viên lớp có kiểu truy cập riêng tư hoặc cuối cùng. Chú thích @Override cũng hỗ trợ các nhà phát triển. Nó giúp trình biên dịch hiểu rằng tại thời điểm này chúng ta sẽ ghi đè hành vi của một phương thức tổ tiên. Nếu chúng ta mắc lỗi trong chữ ký phương thức, trình biên dịch sẽ ngay lập tức cho chúng ta biết về điều đó. Ví dụ:
public static class Parent {
        public void method() {
            System.out.println("parent");
        }
}
public static class Child extends Parent {
        @Override
        public void method(String text) {
            System.out.println("child");
        }
}
Không biên dịch với lỗi: error: phương thức không ghi đè hoặc triển khai phương thức từ siêu kiểu
Đa hình và những người bạn của nó - 6
Việc định nghĩa lại cũng gắn liền với khái niệm “ hiệp phương sai ”. Hãy xem một ví dụ:
public class HelloWorld {
    public static class Parent {
        public Number method() {
            return 1;
        }
    }
    public static class Child extends Parent {
        @Override
        public Integer method() {
            return 2;
        }
    }

    public static void main(String[] args) {
        System.out.println(new Child().method());
    }
}
Bất chấp sự trừu tượng rõ ràng, ý nghĩa của nó là khi ghi đè, chúng ta có thể trả về không chỉ loại đã được chỉ định trong tổ tiên mà còn cả loại cụ thể hơn. Ví dụ: Tổ tiên trả về Số và chúng ta có thể trả về Số nguyên - hậu duệ của Số. Điều tương tự cũng áp dụng cho các ngoại lệ được khai báo trong lần ném của phương thức. Người thừa kế có thể ghi đè phương thức và tinh chỉnh ngoại lệ được ném ra. Nhưng họ không thể mở rộng. Nghĩa là, nếu cấp độ cha ném ra IOException, thì chúng ta có thể ném EOFException chính xác hơn, nhưng chúng ta không thể ném Ngoại lệ. Tương tự như vậy, bạn không thể thu hẹp phạm vi và không thể áp đặt các hạn chế bổ sung. Ví dụ: bạn không thể thêm tĩnh.
Đa hình và những người bạn của nó - 7

Ẩn

Ngoài ra còn có một thứ gọi là " che giấu ". Ví dụ:
public class HelloWorld {
    public static class Parent {
        public static void method() {
            System.out.println("Parent");
        }
    }
    public static class Child extends Parent {
        public static void method() {
            System.out.println("Child");
        }
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();
        parent.method();
        child.method();
    }
}
Đây là một điều khá rõ ràng nếu bạn nghĩ về nó. Các thành viên tĩnh của một lớp thuộc về lớp đó, tức là. vào kiểu của biến. Do đó, điều hợp lý là nếu con thuộc loại Parent thì phương thức sẽ được gọi trên Parent chứ không phải trên con. Nếu chúng ta nhìn vào mã byte, như chúng ta đã làm trước đó, chúng ta sẽ thấy rằng phương thức tĩnh được gọi bằng cách sử dụng lệnh gọi. Điều này giải thích cho JVM rằng nó cần xem xét kiểu chứ không phải bảng phương thức, như Invovvirtual hoặc Invokeinterface đã làm.
Đa hình và những người bạn của nó - 8

Phương pháp quá tải

Chúng ta còn thấy gì nữa trong Hướng dẫn Java Oracle? Trong phần đã nghiên cứu trước đó " Xác định phương pháp " có đôi điều về Quá tải. Nó là gì? Trong tiếng Nga, đây là "quá tải phương thức" và những phương thức như vậy được gọi là "quá tải". Vì vậy, quá tải phương thức. Thoạt nhìn, mọi thứ đều đơn giản. Hãy mở một trình biên dịch Java trực tuyến, ví dụ như tutorialspoint trình biên dịch java trực tuyến .
public class HelloWorld {

	public static void main(String []args){
		HelloWorld hw = new HelloWorld();
		hw.say(1);
		hw.say("1");
	}

	public static void say(Integer number) {
		System.out.println("Integer " + number);
	}
	public static void say(String number) {
		System.out.println("String " + number);
	}
}
Vì vậy, mọi thứ ở đây có vẻ đơn giản. Như đã nêu trong hướng dẫn của Oracle, các phương thức nạp chồng (trong trường hợp này là phương thức say) khác nhau về số lượng và loại đối số được truyền cho phương thức. Bạn không thể khai báo cùng tên và cùng số lượng đối số giống nhau, bởi vì trình biên dịch sẽ không thể phân biệt chúng với nhau. Cần lưu ý ngay một điều rất quan trọng:
Đa hình và những người bạn của nó - 9
Nghĩa là, khi nạp chồng, trình biên dịch sẽ kiểm tra tính chính xác. Nó quan trọng. Nhưng làm thế nào để trình biên dịch thực sự xác định được rằng một phương thức nào đó cần được gọi? Nó sử dụng quy tắc "Phương pháp cụ thể nhất" được mô tả trong đặc tả ngôn ngữ Java: " 15.12.2.5. Chọn phương pháp cụ thể nhất ". Để chứng minh cách thức hoạt động của nó, hãy lấy một ví dụ từ Lập trình viên Java chuyên nghiệp được chứng nhận của Oracle:
public class Overload{
  public void method(Object o) {
    System.out.println("Object");
  }
  public void method(java.io.FileNotFoundException f) {
    System.out.println("FileNotFoundException");
  }
  public void method(java.io.IOException i) {
    System.out.println("IOException");
  }
  public static void main(String args[]) {
    Overload test = new Overload();
    test.method(null);
  }
}
Lấy một ví dụ từ đây: https://github.com/stokito/OCPJP/blob/master/src/ru/habrahabr/bloss/java/OCPJP1/question1/Overload.j... Như bạn có thể thấy, chúng tôi đang vượt qua null cho phương thức. Trình biên dịch cố gắng xác định loại cụ thể nhất. Đối tượng không phù hợp vì mọi thứ đều được thừa hưởng từ anh ấy. Hãy tiếp tục. Có 2 loại ngoại lệ. Chúng ta hãy xem java.io.IOException và thấy rằng có FileNotFoundException trong "Các lớp con được biết trực tiếp". Nghĩa là, hóa ra FileNotFoundException là loại cụ thể nhất. Vì vậy, kết quả sẽ là đầu ra của chuỗi "FileNotFoundException". Nhưng nếu chúng ta thay thế IOException bằng EOFException, hóa ra là chúng ta có hai phương thức ở cùng cấp độ phân cấp trong cây loại, nghĩa là đối với cả hai phương thức đó, IOException là cha. Trình biên dịch sẽ không thể chọn phương thức nào để gọi và sẽ đưa ra lỗi biên dịch: reference to method is ambiguous. Một ví dụ nữa:
public class Overload{
    public static void method(int... array) {
        System.out.println("1");
    }

    public static void main(String args[]) {
        method(1, 2);
    }
}
Nó sẽ xuất ra 1. Không có câu hỏi nào ở đây. Loại int... là một vararg https://docs.oracle.com/javase/8/docs/technotes/guides/lingu/varargs.html và thực sự không gì khác hơn là "cú pháp đường" và thực sự là một int. .. mảng có thể được đọc dưới dạng mảng int[]. Nếu bây giờ chúng ta thêm một phương thức:
public static void method(long a, long b) {
	System.out.println("2");
}
Sau đó nó sẽ hiển thị không phải 1 mà là 2, bởi vì chúng ta đang truyền 2 số và 2 đối số phù hợp hơn một mảng. Nếu chúng ta thêm một phương thức:
public static void method(Integer a, Integer b) {
	System.out.println("3");
}
Khi đó chúng ta vẫn sẽ thấy 2. Bởi vì trong trường hợp này, các giá trị nguyên thủy khớp chính xác hơn so với quyền anh trong Integer. Tuy nhiên, nếu chúng ta thực thi, method(new Integer(1), new Integer(2));nó sẽ in 3. Các hàm tạo trong Java tương tự như các phương thức và vì chúng cũng có thể được sử dụng để lấy chữ ký nên các quy tắc “phân giải quá tải” tương tự sẽ áp dụng cho chúng như các phương thức quá tải. Đặc tả ngôn ngữ Java cho chúng ta biết điều đó trong " 8.8.8. Nạp chồng trình xây dựng ". Quá tải phương thức = Liên kết sớm (hay còn gọi là Liên kết tĩnh) Bạn có thể thường nghe về liên kết sớm và liên kết muộn, còn được gọi là Liên kết tĩnh hoặc Liên kết động. Sự khác biệt giữa chúng rất đơn giản. Đầu là biên dịch, muộn là thời điểm chương trình được thực thi. Do đó, liên kết sớm (liên kết tĩnh) là việc xác định phương thức nào sẽ được gọi cho ai tại thời điểm biên dịch. Chà, liên kết muộn (liên kết động) là việc xác định phương thức nào sẽ gọi trực tiếp tại thời điểm thực hiện chương trình. Như chúng ta đã thấy trước đó (khi chúng ta thay đổi IOException thành EOFException), nếu chúng ta nạp chồng các phương thức để trình biên dịch không thể hiểu nơi thực hiện lệnh gọi nào, thì chúng ta sẽ gặp lỗi thời gian biên dịch: tham chiếu đến phương thức không rõ ràng. Từ mơ hồ dịch từ tiếng Anh có nghĩa là mơ hồ hay không chắc chắn, không chính xác. Hóa ra tình trạng quá tải là ràng buộc sớm, bởi vì việc kiểm tra được thực hiện tại thời điểm biên dịch. Để xác nhận kết luận của chúng tôi, hãy mở Đặc tả ngôn ngữ Java ở chương “ 8.4.9. Quá tải ”:
Đa hình và những người bạn của nó - 10
Hóa ra trong quá trình biên dịch, thông tin về loại và số lượng đối số (có sẵn tại thời điểm biên dịch) sẽ được sử dụng để xác định chữ ký của phương thức. Nếu phương thức này là một trong các phương thức của đối tượng (tức là phương thức phiên bản), lệnh gọi phương thức thực tế sẽ được xác định trong thời gian chạy bằng cách sử dụng tra cứu phương thức động (tức là liên kết động). Để làm cho nó rõ ràng hơn, hãy lấy một ví dụ tương tự như ví dụ đã thảo luận trước đó:
public class HelloWorld {
    public void method(int intNumber) {
        System.out.println("intNumber");
    }
    public void method(Integer intNumber) {
        System.out.println("Integer");
    }
    public void method(String intNumber) {
        System.out.println("Number is: " + intNumber);
    }

    public static void main(String args[]) {
        HelloWorld test = new HelloWorld();
        test.method(2);
    }
}
Hãy lưu mã này vào tệp HelloWorld.java và biên dịch nó bằng cách sử dụng javac HelloWorld.java Bây giờ, hãy xem trình biên dịch của chúng tôi đã viết gì trong mã byte bằng cách chạy lệnh: javap -verbose HelloWorld.
Đa hình và những người bạn của nó - 11
Như đã nêu, trình biên dịch đã xác định rằng một số phương thức ảo sẽ được gọi trong tương lai. Nghĩa là, phần thân phương thức sẽ được xác định khi chạy. Nhưng tại thời điểm biên dịch, trong cả 3 phương pháp, trình biên dịch đã chọn phương thức phù hợp nhất nên chỉ ra con số:"invokevirtual #13"
Đa hình và những người bạn của nó - 12
Đây là loại phương pháp gì? Đây là một liên kết đến phương pháp. Nói một cách đại khái, đây là một số manh mối mà qua đó, trong thời gian chạy, Máy ảo Java thực sự có thể xác định phương thức nào cần tìm để thực thi. Bạn có thể tìm thêm thông tin chi tiết trong siêu bài viết: " JVM xử lý quá tải và ghi đè phương thức nội bộ như thế nào ".

Tóm tắt

Vì vậy, chúng tôi phát hiện ra rằng Java, với tư cách là một ngôn ngữ hướng đối tượng, hỗ trợ tính đa hình. Đa hình có thể là tĩnh (Liên kết tĩnh) hoặc động (Liên kết động). Với tính đa hình tĩnh, còn được gọi là liên kết sớm, trình biên dịch sẽ xác định phương thức nào sẽ được gọi và ở đâu. Điều này cho phép sử dụng một cơ chế như quá tải. Với tính đa hình động, còn được gọi là liên kết muộn, dựa trên chữ ký được tính toán trước đó của một phương thức, một phương thức sẽ được tính toán trong thời gian chạy dựa trên đối tượng nào được sử dụng (tức là phương thức của đối tượng nào được gọi). Bạn có thể xem cách các cơ chế này hoạt động bằng cách sử dụng mã byte. Quá tải xem xét các chữ ký của phương thức và khi giải quyết tình trạng quá tải, tùy chọn cụ thể nhất (chính xác nhất) sẽ được chọn. Tính năng ghi đè xem xét loại để xác định phương thức nào có sẵn và bản thân các phương thức đó được gọi dựa trên đối tượng. Cũng như các tài liệu về chủ đề: #Viacheslav
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION