CodeGym /Java Blog /Acak /Polimorfisme Jawa
John Squirrels
Level 41
San Francisco

Polimorfisme Jawa

Dipublikasikan di grup Acak
Pertanyaan terkait OOP merupakan bagian integral dari wawancara teknis untuk posisi pengembang Java di perusahaan IT. Pada artikel ini, kita akan berbicara tentang satu prinsip OOP – polimorfisme. Kami akan fokus pada aspek-aspek yang sering ditanyakan selama wawancara, dan juga memberikan beberapa contoh untuk kejelasan.

Apa polimorfisme di Jawa?

Polimorfisme adalah kemampuan program untuk memperlakukan objek dengan antarmuka yang sama dengan cara yang sama, tanpa informasi tentang jenis spesifik objek tersebut. Jika Anda menjawab pertanyaan tentang apa itu polimorfisme, kemungkinan besar Anda akan diminta untuk menjelaskan maksud Anda. Tanpa memicu banyak pertanyaan tambahan, ungkapkan semuanya untuk pewawancara sekali lagi. Waktu wawancara: polimorfisme di Jawa - 1Anda bisa mulai dengan fakta bahwa pendekatan OOP melibatkan pembuatan program Java berdasarkan interaksi antar objek, yang didasarkan pada kelas. Kelas adalah cetak biru (templat) yang sebelumnya ditulis yang digunakan untuk membuat objek dalam program. Selain itu, sebuah kelas selalu memiliki tipe tertentu, yang dengan gaya pemrograman yang baik memiliki nama yang menunjukkan tujuannya. Lebih lanjut, dapat dicatat bahwa karena Java memiliki tipe yang kuat, kode program harus selalu menentukan tipe objek ketika variabel dideklarasikan. Tambahkan ke fakta bahwa pengetikan yang ketat meningkatkan keamanan dan keandalan kode, dan memungkinkan, bahkan saat kompilasi, untuk mencegah kesalahan karena jenis ketidakcocokan (misalnya, mencoba membagi string dengan angka). Secara alami, kompiler harus "tahu" tipe yang dideklarasikan – bisa berupa kelas dari JDK atau kelas yang kita buat sendiri. Tunjukkan kepada pewawancara bahwa kode kita tidak hanya dapat menggunakan objek dari tipe yang ditunjukkan dalam deklarasi tetapi juga keturunannya.Ini adalah poin penting: kita dapat bekerja dengan banyak tipe berbeda sebagai satu tipe (asalkan tipe ini berasal dari tipe dasar). Ini juga berarti bahwa jika kita mendeklarasikan sebuah variabel yang bertipe superclass, maka kita dapat menugaskan instance dari salah satu turunannya ke variabel tersebut. Pewawancara akan suka jika Anda memberi contoh. Pilih beberapa kelas yang dapat dibagi oleh (kelas dasar untuk) beberapa kelas dan buat beberapa di antaranya mewarisinya. Kelas dasar:

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 "I'm " + name + ". I'm " + age + " years old.";
    }
}
Di subclass, ganti metode dari kelas dasar:

public class ElectricBoogieDancer extends Dancer {
    public ElectricBoogieDancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString () + " I dance the electric boogie!");
    }
}

public class Breakdancer extends Dancer {

    public Breakdancer(String name, int age) {
        super(name, age);
    }
// Override the method of the base class
    @Override
    public void dance() {
        System.out.println(toString() + " I breakdance!");
    }
}
Contoh polimorfisme dan bagaimana objek ini dapat digunakan dalam program:

public class Main {

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

        Dancer breakdancer = new Breakdancer("Jay", 19); // Widening conversion to the base type 
        Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20); // Widening conversion to the base type

        List<dancer> disco = Arrays.asList(dancer, breakdancer, electricBoogieDancer);
        for (Dancer d : disco) {
            d.dance(); // Call the polymorphic method
        }
    }
}
Dalam metode utama , tunjukkan garis

Dancer breakdancer = new Breakdancer("Jay", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Marcia", 20);
mendeklarasikan variabel superclass dan menugaskannya sebagai objek yang merupakan turunan dari salah satu turunannya. Anda kemungkinan besar akan ditanya mengapa kompiler tidak membalik ketidakkonsistenan tipe yang dideklarasikan di sisi kiri dan kanan operator penugasan — lagipula, Java diketik dengan kuat. Jelaskan bahwa konversi tipe pelebaran sedang bekerja di sini — referensi ke objek diperlakukan seperti referensi ke kelas dasarnya. Terlebih lagi, setelah menemukan konstruksi seperti itu dalam kode, kompiler melakukan konversi secara otomatis dan implisit. Kode contoh menunjukkan bahwa tipe yang dideklarasikan di sisi kiri operator penugasan ( Dancer ) memiliki beberapa bentuk (tipe), yang dideklarasikan di sisi kanan ( Breakdancer , ElectricBoogieDancer). Setiap bentuk dapat memiliki perilaku uniknya sendiri sehubungan dengan fungsi umum yang didefinisikan dalam superclass ( metode dansa ). Artinya, sebuah metode yang dideklarasikan dalam superclass dapat diimplementasikan secara berbeda pada keturunannya. Dalam hal ini, kita berurusan dengan penggantian metode, yang justru menciptakan banyak bentuk (perilaku). Ini dapat dilihat dengan menjalankan kode dalam metode utama: Keluaran program: Saya Fred. Saya berusia 18 tahun. Saya menari seperti orang lain. Saya Jay. Usia saya 19 tahun. Saya breakdance! Saya Marsia. Saya 20 tahun. Saya menari boogie listrik! Jika kita tidak mengganti metode di subclass, maka kita tidak akan mendapatkan perilaku yang berbeda. Misalnya,kelas ElectricBoogieDancer , maka output dari program ini adalah: Saya Fred. Saya berusia 18 tahun. Saya menari seperti orang lain. Saya Jay. Usia saya 19 tahun. Saya menari seperti orang lain. Saya Marsia. Saya 20 tahun. Saya menari seperti orang lain. Dan ini berarti tidak masuk akal untuk membuat kelas Breakdancer dan ElectricBoogieDancer . Di mana tepatnya prinsip polimorfisme terwujud? Di mana objek digunakan dalam program tanpa mengetahui jenis spesifiknya? Dalam contoh kita, ini terjadi ketika metode dance() dipanggil pada objek Dancer d . Di Java, polimorfisme berarti program tidak perlu mengetahui apakah objeknya adalah aBreakdancer atau ElectricBoogieDancer . Yang penting itu adalah keturunan dari kelas Dancer . Dan jika menyebutkan keturunan, perlu diperhatikan bahwa pewarisan di Jawa tidak hanya extends , tetapi juga implements. Sekarang saatnya untuk menyebutkan bahwa Java tidak mendukung pewarisan berganda — setiap jenis dapat memiliki satu induk (superclass) dan jumlah keturunan (subclass) yang tidak terbatas. Oleh karena itu, antarmuka digunakan untuk menambahkan beberapa set fungsi ke kelas. Dibandingkan dengan subclass (warisan), interface lebih sedikit digabungkan dengan parent class. Mereka digunakan sangat luas. Di Java, interface adalah tipe referensi, sehingga program dapat mendeklarasikan variabel dari tipe interface. Sekarang saatnya memberi contoh. Buat antarmuka:

public interface CanSwim {
    void swim();
}
Untuk kejelasan, kami akan mengambil berbagai kelas yang tidak terkait dan membuatnya mengimplementasikan antarmuka:

public class Human implements CanSwim {
    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 inflated tube.");
    }

    @Override
    public String toString() {
        return "I'm " + name + ". I'm " + age + " years old.";
    }

}
 
public class Fish implements CanSwim {
    private String name;

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

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

    }

public class UBoat implements CanSwim {

    private int speed;

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

    @Override
    public void swim() {
        System.out.println("I'm a submarine that swims through the water by rotating screw propellers. My speed is " + speed + " knots.");
    }
}
metode utama :

public class Main {

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

        List<swim> swimmers = Arrays.asList(human, fish, boat);
        for (Swim s : swimmers) {
            s.swim();
        }
    }
}
Hasil pemanggilan metode polimorfik yang didefinisikan dalam antarmuka menunjukkan kepada kita perbedaan perilaku tipe yang mengimplementasikan antarmuka ini. Dalam kasus kita, ini adalah string berbeda yang ditampilkan oleh metode swim . Setelah mempelajari contoh kami, pewawancara mungkin bertanya mengapa menjalankan kode ini di metode utama

for (Swim s : swimmers) {
            s.swim();        
}
menyebabkan metode utama yang didefinisikan dalam subkelas kita dipanggil? Bagaimana implementasi metode yang diinginkan dipilih saat program sedang berjalan? Untuk menjawab pertanyaan ini, Anda perlu menjelaskan pengikatan yang terlambat (dinamis). Mengikat berarti membuat pemetaan antara pemanggilan metode dan implementasi kelas spesifiknya. Intinya, kode menentukan mana dari tiga metode yang ditentukan dalam kelas yang akan dieksekusi. Java menggunakan pengikatan terlambat secara default, yaitu pengikatan terjadi saat runtime dan bukan pada waktu kompilasi seperti halnya dengan pengikatan awal. Ini berarti bahwa ketika kompiler mengkompilasi kode ini

for (Swim s : swimmers) {
            s.swim();        
}
tidak tahu kelas mana ( Manusia , Ikan , atau Uboat ) yang memiliki kode yang akan dijalankan saat berenangmetode disebut. Ini ditentukan hanya ketika program dijalankan, berkat mekanisme pengikatan dinamis (memeriksa tipe objek saat runtime dan memilih implementasi yang tepat untuk tipe ini). Jika Anda ditanya bagaimana penerapannya, Anda dapat menjawab bahwa saat memuat dan menginisialisasi objek, JVM membuat tabel dalam memori dan menautkan variabel dengan nilainya dan objek dengan metodenya. Dalam melakukannya, jika sebuah kelas diwariskan atau mengimplementasikan antarmuka, urutan pertama bisnis adalah memeriksa keberadaan metode yang diganti. Jika ada, mereka terikat pada tipe ini. Jika tidak, pencarian metode yang cocok akan berpindah ke kelas yang satu tingkat lebih tinggi (induk) dan seterusnya hingga akar dalam hierarki bertingkat. Dalam hal polimorfisme dalam OOP dan penerapannya dalam kode, kami mencatat bahwa adalah praktik yang baik untuk menggunakan kelas abstrak dan antarmuka untuk memberikan definisi abstrak dari kelas dasar. Praktik ini mengikuti prinsip abstraksi — mengidentifikasi perilaku dan properti umum dan menempatkannya di kelas abstrak, atau mengidentifikasi hanya perilaku umum dan meletakkannya di antarmuka. Merancang dan membuat hierarki objek berdasarkan antarmuka dan pewarisan kelas diperlukan untuk mengimplementasikan polimorfisme. Mengenai polimorfisme dan inovasi di Java, kami mencatat bahwa mulai dari Java 8, saat membuat kelas abstrak dan antarmuka dimungkinkan untuk menggunakan atau mengidentifikasi hanya perilaku umum dan memasukkannya ke dalam antarmuka. Merancang dan membuat hierarki objek berdasarkan antarmuka dan pewarisan kelas diperlukan untuk mengimplementasikan polimorfisme. Mengenai polimorfisme dan inovasi di Java, kami mencatat bahwa mulai dari Java 8, saat membuat kelas abstrak dan antarmuka dimungkinkan untuk menggunakan atau mengidentifikasi hanya perilaku umum dan memasukkannya ke dalam antarmuka. Merancang dan membuat hierarki objek berdasarkan antarmuka dan pewarisan kelas diperlukan untuk mengimplementasikan polimorfisme. Mengenai polimorfisme dan inovasi di Java, kami mencatat bahwa mulai dari Java 8, saat membuat kelas abstrak dan antarmuka dimungkinkan untuk menggunakankata kunci default untuk menulis implementasi default untuk metode abstrak di kelas dasar. Misalnya:

public interface CanSwim {
    default void swim() {
        System.out.println("I just swim");
    }
}
Terkadang pewawancara bertanya tentang bagaimana metode di kelas dasar harus dideklarasikan agar prinsip polimorfisme tidak dilanggar. Jawabannya sederhana: metode ini tidak boleh static , private atau final . Private membuat metode hanya tersedia di dalam kelas, jadi Anda tidak akan bisa menimpanya di subkelas. Statis mengaitkan metode dengan kelas daripada objek apa pun, sehingga metode superclass akan selalu dipanggil. Dan final membuat metode tidak dapat diubah dan disembunyikan dari subkelas.

Apa yang diberikan polimorfisme kepada kita?

Anda juga kemungkinan besar akan ditanya tentang bagaimana polimorfisme menguntungkan kita. Anda dapat menjawab ini secara singkat tanpa terjebak dalam detail berbulu:
  1. Itu memungkinkan untuk mengganti implementasi kelas. Pengujian dibangun di atasnya.
  2. Ini memfasilitasi perluasan, membuatnya lebih mudah untuk membuat fondasi yang dapat dibangun di masa depan. Menambahkan tipe baru berdasarkan yang sudah ada adalah cara paling umum untuk memperluas fungsionalitas program OOP.
  3. Ini memungkinkan Anda menggabungkan objek yang memiliki tipe atau perilaku yang sama ke dalam satu koleksi atau larik dan menanganinya secara seragam (seperti dalam contoh kami, di mana kami memaksa semua orang untuk menari() atau berenang() :)
  4. Fleksibilitas dalam membuat tipe baru: Anda dapat memilih penerapan metode induk atau menimpanya dalam subkelas.

Beberapa kata perpisahan

Polimorfisme adalah topik yang sangat penting dan luas. Ini adalah subjek dari hampir setengah dari artikel ini tentang OOP di Jawa dan merupakan bagian yang baik dari dasar bahasa. Anda tidak akan dapat menghindari mendefinisikan prinsip ini dalam sebuah wawancara. Jika Anda tidak mengetahuinya atau tidak memahaminya, wawancara mungkin akan segera berakhir. Jadi jangan menjadi pemalas — nilai pengetahuan Anda sebelum wawancara dan perbarui jika perlu.

Lebih banyak membaca:

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION