JavaRush /Blog Java /Random-MS /Polimorfisme di Jawa

Polimorfisme di Jawa

Diterbitkan dalam kumpulan
Soalan tentang OOP adalah sebahagian daripada temu duga teknikal untuk jawatan pembangun Java dalam syarikat IT. Dalam artikel ini kita akan bercakap tentang salah satu prinsip OOP - polimorfisme. Kami akan memberi tumpuan kepada aspek yang sering ditanya semasa temu bual, dan juga memberikan contoh kecil untuk kejelasan.

Apakah polimorfisme?

Polimorfisme ialah keupayaan atur cara untuk menggunakan objek secara identik dengan antara muka yang sama tanpa maklumat tentang jenis objek tertentu ini. Jika anda menjawab soalan apakah polimorfisme dengan cara ini, kemungkinan besar anda akan diminta untuk menerangkan maksud anda. Sekali lagi, tanpa meminta banyak soalan tambahan, susun segala-galanya untuk penemuduga.

Polimorfisme di Jawa pada temu bual - 1
Kita boleh mulakan dengan fakta bahawa pendekatan OOP melibatkan membina program Java berdasarkan interaksi objek yang berdasarkan kelas. Kelas ialah lukisan pra-tulis (templat) mengikut objek dalam program yang akan dibuat. Selain itu, kelas sentiasa mempunyai jenis tertentu, yang, dengan gaya pengaturcaraan yang baik, "memberitahu" tujuannya dengan namanya. Selanjutnya, boleh diperhatikan bahawa memandangkan Java adalah bahasa yang ditaip dengan kuat, kod program sentiasa perlu menunjukkan jenis objek semasa mengisytiharkan pembolehubah. Tambahkan pada ini bahawa penaipan yang ketat meningkatkan keselamatan kod dan kebolehpercayaan program dan membolehkan anda menghalang ralat ketidakserasian jenis (contohnya, percubaan untuk membahagikan rentetan dengan nombor) pada peringkat penyusunan. Sememangnya, pengkompil mesti "mengetahui" jenis yang diisytiharkan - ini boleh menjadi kelas daripada JDK atau yang kami cipta sendiri. Sila ambil perhatian kepada penemuduga bahawa apabila bekerja dengan kod program, kami boleh menggunakan bukan sahaja objek jenis yang kami tetapkan semasa mengisytiharkan, tetapi juga keturunannya. Ini adalah perkara penting: kita boleh menganggap banyak jenis seolah-olah ia hanya satu (selagi jenis tersebut berasal daripada jenis asas). Ini juga bermakna, setelah mengisytiharkan pembolehubah jenis superclass, kita boleh memberikannya nilai salah satu keturunannya. Penemuduga akan suka jika anda memberi contoh. Pilih beberapa objek yang boleh menjadi biasa (asas) untuk sekumpulan objek dan warisi beberapa kelas daripadanya. Kelas asas:
public class Dancer {
    private String name;
    private int age;

    public Dancer(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void dance() {
        System.out.println(toString() + "I dance like everyone else.");
    }

    @Override
    public String toString() {
        return "Я " + name + ", to me " + age + " years. " ;
    }
}
Dalam keturunan, ganti kaedah kelas asas:
public class ElectricBoogieDancer extends Dancer {
    public ElectricBoogieDancer(String name, int age) {
        super(name, age);
    }
// overriding the base class method
    @Override
    public void dance() {
        System.out.println( toString() + "I dance electric boogie!");
    }
}

public class BreakDankDancer extends Dancer{

    public BreakDankDancer(String name, int age) {
        super(name, age);
    }
// overriding the base class method
    @Override
    public void dance(){
        System.out.println(toString() + "I'm breakdancing!");
    }
}
Contoh polimorfisme dalam Java dan penggunaan objek dalam program:
public class Main {

    public static void main(String[] args) {
        Dancer dancer = new Dancer("Anton", 18);

        Dancer breakDanceDancer = new BreakDankDancer("Alexei", 19);// upcast to base type
        Dancer electricBoogieDancer = new ElectricBoogieDancer("Igor", 20); // upcast to base type

        List<Dancer> discotheque = Arrays.asList(dancer, breakDanceDancer, electricBoogieDancer);
        for (Dancer d : discotheque) {
            d.dance();// polymorphic method call
        }
    }
}
mainTunjukkan dalam kod kaedah apa yang ada dalam baris:
Dancer breakDanceDancer = new BreakDankDancer("Alexei", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Igor", 20);
Kami mengisytiharkan pembolehubah jenis superclass dan memberikannya nilai salah satu keturunan. Kemungkinan besar, anda akan ditanya mengapa pengkompil tidak akan mengadu tentang ketidakpadanan antara jenis yang diisytiharkan ke kiri dan ke kanan tanda tugasan, memandangkan Java mempunyai penaipan yang ketat. Terangkan bahawa penukaran jenis ke atas berfungsi di sini - rujukan kepada objek ditafsirkan sebagai rujukan kepada kelas asas. Selain itu, pengkompil, setelah menemui pembinaan sedemikian dalam kod, melakukan ini secara automatik dan tersirat. Berdasarkan kod contoh, dapat ditunjukkan bahawa jenis kelas yang diisytiharkan di sebelah kiri tanda tugasan Dancermempunyai beberapa bentuk (jenis) yang diisytiharkan ke kanan BreakDankDancer, ElectricBoogieDancer. Setiap borang boleh mempunyai gelagat uniknya sendiri untuk kefungsian biasa yang ditakrifkan dalam kaedah superclass dance. Iaitu, kaedah yang diisytiharkan dalam superclass boleh dilaksanakan secara berbeza dalam keturunannya. Dalam kes ini, kita berhadapan dengan kaedah mengatasi, dan inilah yang menghasilkan pelbagai bentuk (tingkah laku). Anda boleh melihat ini dengan menjalankan kod kaedah utama untuk pelaksanaan: Output program Saya Anton, saya berumur 18 tahun. Saya menari seperti orang lain. Saya Alexey, saya berumur 19 tahun. Saya breakdance! Saya Igor, saya berumur 20 tahun. Saya menari boogie elektrik! Jika kita tidak menggunakan overriding dalam keturunan, maka kita tidak akan mendapat perlakuan yang berbeza. BreakDankDancerContohnya, jika kita ElectricBoogieDancermengulas kaedah untuk kelas kita dance, output program akan menjadi seperti ini: Saya Anton, saya berumur 18 tahun. Saya menari seperti orang lain. Saya Alexey, saya berumur 19 tahun. Saya menari seperti orang lain. Saya Igor, saya berumur 20 tahun. Saya menari seperti orang lain. dan ini bermakna BreakDankDancertiada ElectricBoogieDancergunanya mencipta kelas baharu. Apakah sebenarnya prinsip polimorfisme Java? Di manakah ia tersembunyi untuk menggunakan objek dalam program tanpa mengetahui jenis khususnya? Dalam contoh kami, ini ialah panggilan kaedah d.dance()pada objek djenis Dancer. Polimorfisme Java bermaksud bahawa program tidak perlu mengetahui jenis objek BreakDankDanceratau objek tersebut ElectricBoogieDancer. Perkara utama ialah ia adalah keturunan kelas Dancer. Dan jika kita bercakap tentang keturunan, perlu diperhatikan bahawa warisan di Jawa bukan sahaja extends, tetapi juga implements. Sekarang adalah masa untuk mengingati bahawa Java tidak menyokong berbilang warisan - setiap jenis boleh mempunyai satu induk (superclass) dan bilangan keturunan yang tidak terhad (subclass). Oleh itu, antara muka digunakan untuk menambah pelbagai fungsi pada kelas. Antara muka mengurangkan gandingan objek kepada induk berbanding dengan warisan dan digunakan secara meluas. Dalam Java, antara muka ialah jenis rujukan, jadi program boleh mengisytiharkan jenis itu sebagai pembolehubah jenis antara muka. Ini adalah masa yang baik untuk memberi contoh. Mari buat antara muka:
public interface Swim {
    void swim();
}
Untuk kejelasan, mari ambil objek yang berbeza dan tidak berkaitan dan laksanakan antara muka di dalamnya:
public class Human implements Swim {
    private String name;
    private int age;

    public Human(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public void swim() {
        System.out.println(toString()+"I swim with an inflatable ring.");
    }

    @Override
    public String toString() {
        return "Я " + name + ", to me " + age + " years. ";
    }

}

public class Fish implements Swim{
    private String name;

    public Fish(String name) {
        this.name = name;
    }

    @Override
    public void swim() {
        System.out.println("I'm a fish " + name + ". I swim by moving my fins.");

    }

public class UBoat implements Swim {

    private int speed;

    public UBoat(int speed) {
        this.speed = speed;
    }

    @Override
    public void swim() {
        System.out.println("The submarine is sailing, rotating the propellers, at a speed" + speed + " knots.");
    }
}
Kaedah main:
public class Main {

    public static void main(String[] args) {
        Swim human = new Human("Anton", 6);
        Swim fish = new Fish("whale");
        Swim boat = new UBoat(25);

        List<Swim> swimmers = Arrays.asList(human, fish, boat);
        for (Swim s : swimmers) {
            s.swim();
        }
    }
}
Hasil daripada melaksanakan kaedah polimorfik yang ditakrifkan dalam antara muka membolehkan kita melihat perbezaan dalam tingkah laku jenis yang melaksanakan antara muka tersebut. Ia terdiri daripada keputusan pelaksanaan kaedah yang berbeza swim. Selepas mengkaji contoh kami, penemuduga mungkin bertanya mengapa, apabila melaksanakan kod darimain
for (Swim s : swimmers) {
            s.swim();
}
Adakah kaedah yang ditakrifkan dalam kelas ini dipanggil untuk objek kami? Bagaimanakah anda memilih pelaksanaan kaedah yang dikehendaki semasa melaksanakan program? Untuk menjawab soalan-soalan ini, kita perlu bercakap tentang pengikatan lewat (dinamik). Dengan mengikat kami bermaksud mewujudkan hubungan antara panggilan kaedah dan pelaksanaan khususnya dalam kelas. Pada asasnya, kod menentukan yang mana antara tiga kaedah yang ditakrifkan dalam kelas akan dilaksanakan. Java secara lalai menggunakan pengikatan lewat (pada masa jalan dan bukannya pada masa penyusunan, seperti halnya dengan pengikatan awal). Ini bermakna apabila menyusun kod
for (Swim s : swimmers) {
            s.swim();
}
pengkompil belum mengetahui kelas mana kod itu berasal Human, Fishatau sama ada Uboatia akan dilaksanakan dalam swim. Ini akan ditentukan hanya apabila program dilaksanakan terima kasih kepada mekanisme penghantaran dinamik - menyemak jenis objek semasa pelaksanaan program dan memilih pelaksanaan kaedah yang dikehendaki untuk jenis ini. Jika anda ditanya bagaimana ini dilaksanakan, anda boleh menjawab bahawa apabila memuatkan dan memulakan objek, JVM membina jadual dalam ingatan, dan di dalamnya mengaitkan pembolehubah dengan nilainya, dan objek dengan kaedahnya. Lebih-lebih lagi, jika objek diwarisi atau melaksanakan antara muka, kehadiran kaedah yang diganti dalam kelasnya disemak terlebih dahulu. Jika ada, mereka terikat dengan jenis ini, jika tidak, kaedah dicari yang ditakrifkan dalam kelas satu tahap yang lebih tinggi (dalam induk) dan seterusnya sehingga ke akar dalam hierarki berbilang peringkat. Bercakap tentang polimorfisme dalam OOP dan pelaksanaannya dalam kod program, kami ambil perhatian bahawa adalah amalan yang baik untuk menggunakan penerangan abstrak untuk menentukan kelas asas menggunakan kelas abstrak serta antara muka. Amalan ini adalah berdasarkan penggunaan pengabstrakan - mengasingkan gelagat dan sifat biasa dan melampirkannya dalam kelas abstrak, atau mengasingkan gelagat biasa sahaja - dalam hal ini kita mencipta antara muka. Membina dan mereka bentuk hierarki objek berdasarkan antara muka dan warisan kelas adalah prasyarat untuk memenuhi prinsip polimorfisme OOP. Mengenai isu polimorfisme dan inovasi dalam Java, kita boleh menyebut bahawa apabila mencipta kelas dan antara muka abstrak, bermula dengan Java 8, adalah mungkin untuk menulis pelaksanaan lalai kaedah abstrak dalam kelas asas menggunakan kata kunci default. Sebagai contoh:
public interface Swim {
    default void swim() {
        System.out.println("Just floating");
    }
}
Kadang-kadang mereka mungkin bertanya tentang keperluan untuk mengisytiharkan kaedah dalam kelas asas supaya prinsip polimorfisme tidak dilanggar. Semuanya mudah di sini: kaedah ini tidak boleh statik , peribadi dan muktamad . Peribadi menjadikan kaedah hanya tersedia dalam kelas dan anda tidak boleh mengatasinya dalam keturunan. Statik menjadikan kaedah sebagai harta kelas, bukan objek, jadi kaedah superclass akan sentiasa dipanggil. Akhir akan menjadikan kaedah itu tidak berubah dan tersembunyi daripada pewarisnya.

Apakah yang diberikan oleh polimorfisme kepada kita di Jawa?

Persoalan tentang apa yang diberikan oleh penggunaan polimorfisme kepada kita kemungkinan besar juga akan timbul. Di sini anda boleh menjawab secara ringkas, tanpa pergi terlalu jauh ke dalam rumpai:
  1. Membolehkan anda menggantikan pelaksanaan objek. Inilah yang menjadi asas ujian.
  2. Menyediakan kebolehkembangan program - menjadi lebih mudah untuk mencipta asas untuk masa hadapan. Menambah jenis baharu berdasarkan yang sedia ada ialah cara paling biasa untuk mengembangkan kefungsian atur cara yang ditulis dalam gaya OOP.
  3. Membolehkan anda menggabungkan objek dengan jenis atau gelagat biasa ke dalam satu koleksi atau tatasusunan dan mengurusnya secara seragam (seperti dalam contoh kami, membuat semua orang menari - kaedah danceatau berenang - kaedah swim).
  4. Fleksibiliti semasa membuat jenis baharu: anda boleh memilih untuk melaksanakan kaedah daripada ibu bapa atau mengatasinya dalam kanak-kanak.

Kata-kata perpisahan untuk perjalanan

Prinsip polimorfisme adalah topik yang sangat penting dan luas. Ia merangkumi hampir separuh daripada OOP Java dan sebahagian besar asas bahasa. Anda tidak akan dapat melepaskan diri dengan mentakrifkan prinsip ini dalam temu bual. Kejahilan atau salah faham mengenainya kemungkinan besar akan menamatkan temu duga. Oleh itu, jangan malas menyemak pengetahuan anda sebelum ujian dan segarkannya jika perlu.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION