JavaRush /Blog Java /Random-MS /Polimorfisme dan rakan-rakannya

Polimorfisme dan rakan-rakannya

Diterbitkan dalam kumpulan
Polimorfisme adalah salah satu prinsip asas pengaturcaraan berorientasikan objek. Ia membolehkan anda memanfaatkan kuasa penaipan Java yang kuat dan menulis kod yang boleh digunakan dan boleh diselenggara. Banyak yang telah diperkatakan tentang dia, tetapi saya harap semua orang boleh mengambil sesuatu yang baru daripada ulasan ini.
Polimorfisme dan rakan-rakannya - 1

pengenalan

Saya rasa kita semua tahu bahawa bahasa pengaturcaraan Java adalah milik Oracle. Oleh itu, laluan kami bermula dengan tapak: www.oracle.com . Terdapat "Menu" pada halaman utama. Di dalamnya, dalam bahagian "Dokumentasi" terdapat subseksyen "Java". Semua yang berkaitan dengan fungsi asas bahasa adalah kepunyaan "dokumentasi Java SE", jadi kami memilih bahagian ini. Bahagian dokumentasi akan dibuka untuk versi terkini, tetapi buat masa ini "Mencari keluaran lain?" Mari pilih pilihan: JDK8. Pada halaman kita akan melihat banyak pilihan yang berbeza. Tetapi kami berminat untuk Belajar Bahasa: " Java Tutorials Learning Paths ". Pada halaman ini kita akan menemui bahagian lain: " Belajar Bahasa Java ". Ini adalah yang paling suci, tutorial tentang asas Java daripada Oracle. Java ialah bahasa pengaturcaraan berorientasikan objek (OOP), jadi pembelajaran bahasa itu walaupun di laman web Oracle bermula dengan perbincangan tentang konsep asas " Konsep Pengaturcaraan Berorientasikan Objek ". Dari nama itu sendiri jelas bahawa Java memberi tumpuan kepada bekerja dengan objek. Daripada subseksyen " What Is an Object? ", jelas bahawa objek di Jawa terdiri daripada keadaan dan tingkah laku. Bayangkan kita ada akaun bank. Jumlah wang dalam akaun adalah keadaan, dan kaedah bekerja dengan keadaan ini adalah tingkah laku. Objek perlu diterangkan entah bagaimana (beritahu keadaan dan tingkah laku yang mungkin mereka miliki) dan penerangan ini ialah class . Apabila kami mencipta objek bagi sesetengah kelas, kami menentukan kelas ini dan ini dipanggil " jenis objek ". Oleh itu dikatakan bahawa Java adalah bahasa yang ditaip kuat, seperti yang dinyatakan dalam spesifikasi bahasa Java dalam bahagian " Bab 4. Jenis, Nilai, dan Pembolehubah ". Bahasa Java mengikut konsep OOP dan menyokong warisan menggunakan kata kunci lanjutan. Mengapa perluasan? Kerana dengan warisan, kelas anak mewarisi tingkah laku dan keadaan kelas induk dan boleh melengkapkannya, i.e. memperluaskan fungsi kelas asas. Antara muka juga boleh ditentukan dalam penerangan kelas menggunakan kata kunci implements. Apabila kelas melaksanakan antara muka, ini bermakna kelas itu mematuhi beberapa kontrak - pengisytiharan oleh pengaturcara kepada seluruh persekitaran bahawa kelas itu mempunyai tingkah laku tertentu. Sebagai contoh, pemain mempunyai pelbagai butang. Butang ini ialah antara muka untuk mengawal tingkah laku pemain dan tingkah laku itu akan mengubah keadaan dalaman pemain (contohnya, kelantangan). Dalam kes ini, keadaan dan tingkah laku sebagai penerangan akan memberikan kelas. Jika kelas melaksanakan antara muka, maka objek yang dicipta oleh kelas ini boleh diterangkan oleh jenis bukan sahaja oleh kelas, tetapi juga oleh antara muka. Mari lihat contoh:

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();
    }
}
Jenis adalah penerangan yang sangat penting. Ia memberitahu bagaimana kita akan bekerja dengan objek, i.e. apakah tingkah laku yang kita harapkan daripada objek tersebut. Tingkah laku adalah kaedah. Oleh itu, mari kita fahami kaedahnya. Di laman web Oracle, kaedah mempunyai bahagian mereka sendiri dalam Tutorial Oracle: " Kaedah Menentukan ". Perkara pertama yang perlu diambil daripada artikel: Tandatangan kaedah ialah nama kaedah dan jenis parameter :
Polimorfisme dan rakan-rakannya - 2
Sebagai contoh, apabila mengisytiharkan kaedah kaedah public void(Objek o), tandatangan akan menjadi nama kaedah dan jenis objek parameter. Jenis pemulangan TIDAK termasuk dalam tandatangan. Ia penting! Seterusnya, mari kita susun kod sumber kita. Seperti yang kita tahu, untuk ini kod mesti disimpan dalam fail dengan nama kelas dan sambungan java. Kod Java disusun menggunakan pengkompil " javac " ke dalam beberapa format perantaraan yang boleh dilaksanakan oleh Mesin Maya Java (JVM). Format perantaraan ini dipanggil bytecode dan terkandung dalam fail dengan sambungan .class. Mari jalankan arahan untuk menyusun: javac MusicPlayer.java Selepas kod java disusun, kita boleh melaksanakannya. Menggunakan utiliti " java " untuk memulakan, proses mesin maya java akan dilancarkan untuk melaksanakan bytecode yang diluluskan dalam fail kelas. Mari jalankan arahan untuk melancarkan aplikasi: java MusicPlayer. Kami akan melihat pada skrin teks yang dinyatakan dalam parameter input kaedah println. Menariknya, mempunyai bytecode dalam fail dengan sambungan .class, kita boleh melihatnya menggunakan utiliti " javap ". Mari jalankan arahan <ocde>javap -c MusicPlayer:
Polimorfisme dan rakan-rakannya - 3
Daripada bytecode kita dapat melihat bahawa memanggil kaedah melalui objek yang jenis kelasnya ditentukan dijalankan menggunakan invokevirtual, dan pengkompil telah mengira tandatangan kaedah mana yang harus digunakan. kenapa invokevirtual? Kerana terdapat panggilan (invoke diterjemahkan sebagai panggilan) kaedah maya. Apakah kaedah maya? Ini ialah kaedah yang badannya boleh ditindih semasa pelaksanaan program. Bayangkan anda mempunyai senarai surat-menyurat antara kunci tertentu (tandatangan kaedah) dan badan (kod) kaedah. Dan surat-menyurat ini antara kunci dan badan kaedah mungkin berubah semasa pelaksanaan program. Oleh itu kaedahnya adalah maya. Secara lalai, dalam Java, kaedah yang TIDAK statik, TIDAK muktamad dan TIDAK peribadi adalah maya. Terima kasih kepada ini, Java menyokong prinsip pengaturcaraan berorientasikan objek polimorfisme. Seperti yang anda mungkin sudah faham, inilah ulasan kami hari ini.

Polimorfisme

Di laman web Oracle dalam Tutorial rasmi mereka terdapat bahagian berasingan: " Polimorfisme ". Mari gunakan Java Online Compiler untuk melihat cara polimorfisme berfungsi di Java. Sebagai contoh, kami mempunyai beberapa kelas abstrak Nombor yang mewakili nombor dalam Java. Apakah yang dibenarkan? Dia mempunyai beberapa teknik asas yang semua waris akan ada. Sesiapa yang mewarisi Number secara literal berkata - "Saya adalah nombor, anda boleh bekerja dengan saya sebagai nombor." Sebagai contoh, untuk mana-mana pengganti anda boleh menggunakan kaedah intValue() untuk mendapatkan nilai Integernya. Jika anda melihat java api untuk Nombor, anda boleh melihat bahawa kaedah itu adalah abstrak, iaitu, setiap pengganti Nombor mesti melaksanakan kaedah ini sendiri. Tetapi apa yang ini memberi kita? Mari lihat contoh:

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));
    }
}
Seperti yang dapat dilihat dari contoh, terima kasih kepada polimorfisme, kita boleh menulis kaedah yang akan menerima hujah dari sebarang jenis sebagai input, yang akan menjadi keturunan Nombor (kita tidak boleh mendapatkan Nombor, kerana ia adalah kelas abstrak). Seperti yang berlaku dengan contoh pemain, dalam kes ini kami mengatakan bahawa kami ingin bekerja dengan sesuatu, seperti Number. Kami tahu bahawa sesiapa sahaja yang merupakan Nombor mesti dapat membekalkan nilai integernya. Dan itu sudah cukup untuk kami. Kami tidak mahu pergi ke perincian pelaksanaan objek tertentu dan mahu bekerja dengan objek ini melalui kaedah biasa untuk semua keturunan Number. Senarai kaedah yang akan tersedia kepada kami akan ditentukan mengikut jenis pada masa penyusunan (seperti yang kita lihat sebelum ini dalam bytecode). Dalam kes ini, jenis kami ialah Nombor. Seperti yang anda boleh lihat daripada contoh, kami menghantar nombor berlainan jenis yang berbeza, iaitu kaedah summ akan menerima Integer, Long dan Double sebagai input. Tetapi apa yang mereka semua mempunyai persamaan ialah mereka adalah keturunan Nombor abstrak, dan oleh itu mengatasi tingkah laku mereka dalam kaedah intValue, kerana setiap jenis tertentu tahu cara menghantar jenis itu kepada Integer. Polimorfisme sedemikian dilaksanakan melalui apa yang dipanggil overriding, dalam Bahasa Inggeris Overriding.
Polimorfisme dan rakan-rakannya - 4
Polimorfisme mengatasi atau dinamik. Jadi, mari kita mulakan dengan menyimpan fail HelloWorld.java dengan kandungan berikut:

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();
    }
}
Mari lakukan javac HelloWorld.javadan javap -c HelloWorld:
Polimorfisme dan rakan-rakannya - 5
Seperti yang anda lihat, dalam kod bait untuk baris dengan panggilan kaedah, rujukan yang sama kepada kaedah untuk memanggil ditunjukkan invokevirtual (#6). Mari lakukannya java HelloWorld. Seperti yang kita dapat lihat, pembolehubah ibu bapa dan anak diisytiharkan dengan jenis Induk, tetapi pelaksanaan itu sendiri dipanggil mengikut objek yang diberikan kepada pembolehubah (iaitu jenis objek). Semasa pelaksanaan program (mereka juga mengatakan dalam masa jalan), JVM, bergantung pada objek, apabila memanggil kaedah menggunakan tandatangan yang sama, melaksanakan kaedah yang berbeza. Iaitu, menggunakan kunci tandatangan yang sepadan, kami mula-mula menerima satu badan kaedah, dan kemudian menerima satu lagi. Bergantung pada objek apa yang terdapat dalam pembolehubah. Penentuan ini pada masa pelaksanaan program kaedah mana yang akan dipanggil juga dipanggil pengikatan lewat atau Pengikatan Dinamik. Iaitu, pemadanan antara tandatangan dan badan kaedah dilakukan secara dinamik, bergantung pada objek yang kaedah dipanggil. Sememangnya, anda tidak boleh mengatasi ahli statik kelas (ahli Kelas), serta ahli kelas dengan jenis akses peribadi atau muktamad. Anotasi @Override turut membantu pembangun. Ia membantu pengkompil memahami bahawa pada ketika ini kita akan mengatasi kelakuan kaedah nenek moyang. Jika kami membuat kesilapan dalam tandatangan kaedah, pengkompil akan segera memberitahu kami mengenainya. Sebagai contoh:

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");
        }
}
Tidak menyusun dengan ralat: ralat: kaedah tidak mengatasi atau melaksanakan kaedah daripada supertype
Polimorfisme dan rakan-rakannya - 6
Definisi semula juga dikaitkan dengan konsep " kovarians ". Mari lihat contoh:

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());
    }
}
Walaupun kekasaran yang jelas, maknanya datang kepada fakta bahawa apabila mengatasi, kita boleh mengembalikan bukan sahaja jenis yang dinyatakan dalam nenek moyang, tetapi juga jenis yang lebih spesifik. Sebagai contoh, nenek moyang mengembalikan Nombor, dan kita boleh mengembalikan Integer - keturunan Nombor. Perkara yang sama berlaku untuk pengecualian yang diisytiharkan dalam lontaran kaedah. Waris boleh mengatasi kaedah dan memperhalusi pengecualian yang dilemparkan. Tetapi mereka tidak boleh berkembang. Iaitu, jika ibu bapa melemparkan IOException, maka kita boleh membuang EOFException yang lebih tepat, tetapi kita tidak boleh membuang Exception. Begitu juga, anda tidak boleh mengecilkan skop dan anda tidak boleh mengenakan sekatan tambahan. Sebagai contoh, anda tidak boleh menambah statik.
Polimorfisme dan rakan-rakannya - 7

Bersembunyi

Terdapat juga perkara seperti " penyorok ". Contoh:

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();
    }
}
Ini adalah perkara yang agak jelas jika anda memikirkannya. Ahli statik kelas tergolong dalam kelas, i.e. kepada jenis pembolehubah. Oleh itu, adalah logik bahawa jika anak adalah jenis Ibu Bapa, maka kaedah itu akan dipanggil pada Ibu Bapa, dan bukan pada anak. Jika kita melihat bytecode, seperti yang kita lakukan sebelum ini, kita akan melihat bahawa kaedah statik dipanggil menggunakan invokestatic. Ini menerangkan kepada JVM bahawa ia perlu melihat jenis, dan bukan pada jadual kaedah, seperti yang dilakukan oleh invokevirtual atau invokeinterface.
Polimorfisme dan rakan-rakannya - 8

Kaedah lebihan beban

Apa lagi yang kita lihat dalam Tutorial Oracle Java? Dalam bahagian " Mentakrifkan Kaedah " yang telah dikaji sebelum ini terdapat sesuatu tentang Lebihan Muatan. Apa ini? Dalam bahasa Rusia ini adalah "kaedah terlebih beban", dan kaedah sedemikian dipanggil "lebih beban". Jadi, kaedah terlebih beban. Pada pandangan pertama, semuanya mudah. Mari buka pengkompil Java dalam talian, contohnya pengkompil java dalam talian tutorialspoint .

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);
	}
}
Jadi, semuanya kelihatan mudah di sini. Seperti yang dinyatakan dalam tutorial Oracle, kaedah terlebih beban (dalam kes ini kaedah katakan) berbeza dalam bilangan dan jenis hujah yang dihantar kepada kaedah tersebut. Anda tidak boleh mengisytiharkan nama yang sama dan bilangan jenis hujah yang sama, kerana pengkompil tidak akan dapat membezakannya antara satu sama lain. Perlu diperhatikan perkara yang sangat penting dengan segera:
Polimorfisme dan rakan-rakannya - 9
Iaitu, apabila terlebih beban, pengkompil menyemak untuk ketepatan. Ia penting. Tetapi bagaimana pengkompil sebenarnya menentukan bahawa kaedah tertentu perlu dipanggil? Ia menggunakan peraturan "Kaedah Paling Spesifik" yang diterangkan dalam spesifikasi bahasa Java: " 15.12.2.5. Memilih Kaedah Paling Spesifik ". Untuk menunjukkan cara ia berfungsi, mari kita ambil contoh daripada Oracle Certified Professional Java Programmer:

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);
  }
}
Ambil contoh dari sini: https://github.com/stokito/OCPJP/blob/master/src/ru/habrahabr/blogs/java/OCPJP1/question1/Overload.j... Seperti yang anda lihat, kami sedang lulus batal kepada kaedah. Pengkompil cuba untuk menentukan jenis yang paling spesifik. Objek tidak sesuai kerana segalanya diwarisi daripadanya. Teruskan. Terdapat 2 kelas pengecualian. Mari lihat java.io.IOException dan lihat bahawa terdapat FileNotFoundException dalam "Subkelas Dikenali Langsung". Iaitu, ternyata FileNotFoundException adalah jenis yang paling spesifik. Oleh itu, hasilnya akan menjadi output rentetan "FileNotFoundException". Tetapi jika kita menggantikan IOException dengan EOFException, ternyata kita mempunyai dua kaedah pada tahap hierarki yang sama dalam pokok jenis, iaitu, untuk kedua-duanya, IOException ialah induknya. Pengkompil tidak akan dapat memilih kaedah yang hendak dipanggil dan akan membuang ralat kompilasi: reference to method is ambiguous. Satu lagi contoh:

public class Overload{
    public static void method(int... array) {
        System.out.println("1");
    }
  
    public static void main(String args[]) {
        method(1, 2);
    }
}
Ia akan mengeluarkan 1. Tiada soalan di sini. Jenis int... ialah vararg https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html dan sebenarnya tidak lebih daripada "gula sintaksis" dan sebenarnya adalah int. .. array boleh dibaca sebagai int[] array. Jika kita sekarang menambah kaedah:

public static void method(long a, long b) {
	System.out.println("2");
}
Kemudian ia akan memaparkan bukan 1, tetapi 2, kerana kami menghantar 2 nombor, dan 2 argumen adalah padanan yang lebih baik daripada satu tatasusunan. Jika kita menambah kaedah:

public static void method(Integer a, Integer b) {
	System.out.println("3");
}
Kemudian kita masih akan melihat 2. Kerana dalam kes ini primitif adalah perlawanan yang lebih tepat daripada tinju dalam Integer. Walau bagaimanapun, jika kita laksanakan, method(new Integer(1), new Integer(2));ia akan mencetak 3. Pembina di Java adalah serupa dengan kaedah, dan memandangkan ia juga boleh digunakan untuk mendapatkan tandatangan, peraturan "peleraian beban lampau" yang sama dikenakan kepada mereka sebagai kaedah terlebih beban. Spesifikasi bahasa Java memberitahu kami demikian dalam " 8.8.8. Pembina Lebih Muatan ". Kelebihan kaedah = Pengikatan awal (aka Pengikatan Statik) Anda sering mendengar tentang pengikatan awal dan lewat, juga dikenali sebagai Pengikatan Statik atau Pengikatan Dinamik. Perbezaan antara mereka sangat mudah. Awal adalah kompilasi, lewat adalah saat program dilaksanakan. Oleh itu, pengikatan awal (pengikatan statik) ialah penentuan kaedah mana yang akan dipanggil pada siapa pada masa penyusunan. Nah, pengikatan lewat (dynamic binding) ialah penentuan kaedah mana yang perlu dipanggil secara langsung pada masa pelaksanaan program. Seperti yang kita lihat sebelum ini (apabila kita menukar IOException kepada EOFException), jika kita membebankan kaedah supaya pengkompil tidak dapat memahami tempat untuk membuat panggilan, maka kita akan mendapat ralat masa kompilasi: rujukan kepada kaedah adalah samar-samar. Perkataan ambiguous diterjemahkan daripada bahasa Inggeris bermaksud ambiguous atau tidak pasti, tidak tepat. Ternyata beban berlebihan mengikat awal, kerana semakan dilakukan pada masa penyusunan. Untuk mengesahkan kesimpulan kami, mari buka Spesifikasi Bahasa Java di bab " 8.4.9. Lebihan ":
Polimorfisme dan rakan-rakannya - 10
Ternyata semasa penyusunan, maklumat tentang jenis dan bilangan hujah (yang tersedia pada masa penyusunan) akan digunakan untuk menentukan tandatangan kaedah. Jika kaedah ialah salah satu kaedah objek (iaitu, kaedah contoh), panggilan kaedah sebenar akan ditentukan pada masa jalan menggunakan carian kaedah dinamik (iaitu, pengikatan dinamik). Untuk menjadikannya lebih jelas, mari kita ambil contoh yang serupa dengan yang dibincangkan sebelum ini:

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);
    }
}
Mari kita simpan kod ini ke fail HelloWorld.java dan kompilasinya menggunakan javac HelloWorld.java Sekarang mari kita lihat apa yang ditulis oleh pengkompil kami dalam kod bait dengan menjalankan arahan: javap -verbose HelloWorld.
Polimorfisme dan rakan-rakannya - 11
Seperti yang dinyatakan, pengkompil telah menentukan bahawa beberapa kaedah maya akan dipanggil pada masa hadapan. Iaitu, badan kaedah akan ditakrifkan pada masa jalan. Tetapi pada masa penyusunan, daripada ketiga-tiga kaedah, pengkompil memilih yang paling sesuai, jadi ia menunjukkan nombor:"invokevirtual #13"
Polimorfisme dan rakan-rakannya - 12
Apakah jenis methodref ini? Ini adalah pautan kepada kaedah. Secara kasarnya, ini adalah beberapa petunjuk yang, pada masa jalan, Mesin Maya Java sebenarnya boleh menentukan kaedah yang hendak dicari untuk dilaksanakan. Butiran lanjut boleh didapati dalam artikel super: " Bagaimana JVM Mengendalikan Kaedah Lebih Muatan Dan Mengatasi Secara Dalaman ".

Merumuskan

Jadi, kami mendapati bahawa Java, sebagai bahasa berorientasikan objek, menyokong polimorfisme. Polimorfisme boleh menjadi statik (Static Binding) atau dinamik (Dynamic Binding). Dengan polimorfisme statik, juga dikenali sebagai pengikatan awal, pengkompil menentukan kaedah yang harus dipanggil dan di mana. Ini membolehkan penggunaan mekanisme seperti lebihan beban. Dengan polimorfisme dinamik, juga dikenali sebagai pengikatan lewat, berdasarkan tandatangan kaedah yang dikira sebelumnya, kaedah akan dikira pada masa jalan berdasarkan objek yang digunakan (iaitu, kaedah objek mana yang dipanggil). Cara mekanisme ini berfungsi boleh dilihat menggunakan bytecode. Kelebihan beban melihat tandatangan kaedah, dan apabila menyelesaikan beban berlebihan, pilihan yang paling spesifik (paling tepat) dipilih. Overriding melihat jenis untuk menentukan kaedah yang tersedia, dan kaedah itu sendiri dipanggil berdasarkan objek. Serta bahan mengenai topik: #Viacheslav
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION