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

Polimorfisme di Jawa

Dipublikasikan di grup Random-ID
Pertanyaan tentang OOP merupakan bagian integral dari wawancara teknis untuk posisi pengembang Java di perusahaan IT. Pada artikel ini kita akan membahas salah satu prinsip OOP - polimorfisme. Kami akan fokus pada aspek-aspek yang sering ditanyakan saat wawancara, dan juga memberikan contoh-contoh kecil untuk kejelasan.

Apa itu polimorfisme?

Polimorfisme adalah kemampuan suatu program untuk menggunakan objek dengan antarmuka yang sama secara identik tanpa informasi tentang tipe spesifik objek tersebut. Jika Anda menjawab pertanyaan apa itu polimorfisme dengan cara ini, kemungkinan besar Anda akan diminta menjelaskan maksud Anda. Sekali lagi, tanpa menanyakan banyak pertanyaan tambahan, bereskan semuanya untuk pewawancara.

Polimorfisme di Jawa saat wawancara - 1
Kita bisa mulai dengan fakta bahwa pendekatan OOP melibatkan pembuatan program Java berdasarkan interaksi objek yang didasarkan pada kelas. Kelas adalah gambar (templat) yang telah ditulis sebelumnya sesuai dengan objek mana dalam program yang akan dibuat. Selain itu, sebuah kelas selalu memiliki tipe tertentu, yang, dengan gaya pemrograman yang baik, “memberitahukan” tujuannya melalui namanya. Lebih lanjut, dapat dicatat bahwa karena Java adalah bahasa dengan tipe yang kuat, kode program selalu perlu menunjukkan tipe objek saat mendeklarasikan variabel. Selain itu, pengetikan yang ketat meningkatkan keamanan kode dan keandalan program serta memungkinkan Anda mencegah kesalahan ketidakcocokan tipe (misalnya, upaya membagi string dengan angka) pada tahap kompilasi. Secara alami, kompiler harus “mengetahui” tipe yang dideklarasikan - ini bisa berupa kelas dari JDK atau yang kita buat sendiri. Harap perhatikan pewawancara bahwa ketika bekerja dengan kode program, kita tidak hanya dapat menggunakan objek dari tipe yang kita tetapkan saat mendeklarasikan, tetapi juga turunannya. Ini adalah poin penting: kita dapat memperlakukan banyak tipe seolah-olah mereka hanya satu (asalkan tipe tersebut berasal dari tipe dasar). Ini juga berarti bahwa, setelah mendeklarasikan variabel bertipe superkelas, kita dapat memberinya nilai dari salah satu turunannya. Pewawancara akan suka jika Anda memberi contoh. Pilih beberapa objek yang umum (basis) untuk sekelompok objek dan mewarisi beberapa kelas darinya. 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 "Я " + name + ", to me " + age + " years. " ;
    }
}
Di turunannya, ganti metode kelas dasar:
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 di Java dan penggunaan objek dalam suatu 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 kode metode apa yang ada di baris:
Dancer breakDanceDancer = new BreakDankDancer("Alexei", 19);
Dancer electricBoogieDancer = new ElectricBoogieDancer("Igor", 20);
Kami mendeklarasikan variabel tipe superclass dan memberinya nilai salah satu turunannya. Kemungkinan besar, Anda akan ditanya mengapa kompiler tidak akan mengeluh tentang ketidakcocokan antara tipe yang dideklarasikan di kiri dan kanan tanda penugasan, karena Java memiliki pengetikan yang ketat. Jelaskan bahwa konversi tipe ke atas berfungsi di sini - referensi ke suatu objek ditafsirkan sebagai referensi ke kelas dasar. Selain itu, kompiler, setelah menemukan konstruksi seperti itu dalam kode, melakukan ini secara otomatis dan implisit. Berdasarkan contoh kode terlihat bahwa tipe kelas yang dideklarasikan di sebelah kiri tanda penugasan Dancermempunyai beberapa bentuk (tipe) yang dideklarasikan di sebelah kanan BreakDankDancer, ElectricBoogieDancer. Masing-masing formulir dapat memiliki perilaku uniknya sendiri untuk fungsionalitas umum yang ditentukan dalam metode superkelas dance. Artinya, metode yang dideklarasikan dalam superkelas dapat diimplementasikan secara berbeda pada turunannya. Dalam hal ini, kita berurusan dengan penggantian metode, dan inilah yang menciptakan berbagai bentuk (perilaku). Anda dapat melihatnya dengan menjalankan kode metode utama untuk eksekusi: Keluaran program Saya Anton, umur saya 18 tahun. Saya menari seperti orang lain. Saya Alexei, umur saya 19 tahun. aku menari breakdance! Saya Igor, umur saya 20 tahun. Saya menari boogie listrik! Jika kita tidak menggunakan overriding pada turunannya, maka kita tidak akan mendapatkan perilaku yang berbeda. BreakDankDancerMisalnya kita ElectricBoogieDancermengomentari metode untuk kelas kita dance, maka keluaran programnya akan seperti ini: Saya Anton, umur saya 18 tahun. Saya menari seperti orang lain. Saya Alexei, umur saya 19 tahun. Saya menari seperti orang lain. Saya Igor, umur saya 20 tahun. Saya menari seperti orang lain. dan ini berarti tidak ada gunanya membuat BreakDankDancerkelas baru ElectricBoogieDancer. Apa sebenarnya prinsip polimorfisme Java? Di manakah tersembunyi untuk menggunakan suatu objek dalam suatu program tanpa mengetahui tipe spesifiknya? Dalam contoh kita, ini adalah pemanggilan metode d.dance()pada objek dbertipe Dancer. Polimorfisme Java berarti bahwa program tidak perlu mengetahui tipe objek BreakDankDanceratau objek apa yang akan dibuat ElectricBoogieDancer. Yang utama adalah ia adalah keturunan kelas Dancer. Dan jika kita berbicara mengenai keturunan, maka perlu diketahui bahwa pewarisan di jawa tidak hanya sekedar extends, tetapi juga implements. Sekaranglah waktunya untuk mengingat bahwa Java tidak mendukung pewarisan berganda - setiap tipe dapat memiliki satu induk (superkelas) dan jumlah keturunan (subkelas) yang tidak terbatas. Oleh karena itu, antarmuka digunakan untuk menambahkan beberapa fungsi ke kelas. Antarmuka mengurangi penggabungan objek ke induk dibandingkan dengan warisan dan digunakan secara luas. Di Java, antarmuka adalah tipe referensi, sehingga program dapat mendeklarasikan tipe tersebut menjadi variabel dari tipe antarmuka. Ini saat yang tepat untuk memberi contoh. Mari buat antarmuka:
public interface Swim {
    void swim();
}
Untuk lebih jelasnya, mari kita ambil objek yang berbeda dan tidak berhubungan dan mengimplementasikan antarmuka 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.");
    }
}
Metode 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 dari mengeksekusi metode polimorfik yang didefinisikan dalam sebuah antarmuka memungkinkan kita untuk melihat perbedaan perilaku tipe-tipe yang mengimplementasikan antarmuka tersebut. Mereka terdiri dari hasil eksekusi metode yang berbeda swim. Setelah mempelajari contoh kita, pewawancara mungkin bertanya mengapa, ketika mengeksekusi kode tersebutmain
for (Swim s : swimmers) {
            s.swim();
}
Apakah metode yang didefinisikan dalam kelas ini dipanggil untuk objek kita? Bagaimana Anda memilih implementasi metode yang diinginkan saat menjalankan suatu program? Untuk menjawab pertanyaan-pertanyaan ini, kita perlu membicarakan tentang pengikatan yang terlambat (dinamis). Yang kami maksud dengan mengikat adalah membangun koneksi antara pemanggilan metode dan implementasi spesifiknya di kelas. Pada dasarnya, kode menentukan mana dari tiga metode yang ditentukan dalam kelas yang akan dieksekusi. Java secara default menggunakan pengikatan akhir (saat runtime, bukan pada waktu kompilasi, seperti halnya pengikatan awal). Artinya saat mengkompilasi kode
for (Swim s : swimmers) {
            s.swim();
}
kompiler belum mengetahui dari kelas mana kode tersebut berasal Human, Fishatau apakah Uboatkode tersebut akan dieksekusi di swim. Ini akan ditentukan hanya ketika program dijalankan berkat mekanisme pengiriman dinamis - memeriksa jenis objek selama eksekusi program dan memilih implementasi metode yang diinginkan untuk jenis ini. Jika Anda ditanya bagaimana hal ini diterapkan, Anda dapat menjawab bahwa saat memuat dan menginisialisasi objek, JVM membuat tabel di memori, dan di dalamnya mengaitkan variabel dengan nilainya, dan objek dengan metodenya. Selain itu, jika suatu objek diwarisi atau mengimplementasikan antarmuka, keberadaan metode yang diganti di kelasnya akan diperiksa terlebih dahulu. Jika ada, mereka diikat ke tipe ini, jika tidak, dicari metode yang didefinisikan di kelas satu tingkat lebih tinggi (di induk) dan seterusnya hingga ke akar dalam hierarki multi-level. Berbicara tentang polimorfisme dalam OOP dan implementasinya dalam kode program, kami mencatat bahwa praktik yang baik adalah menggunakan deskripsi abstrak untuk mendefinisikan kelas dasar menggunakan kelas abstrak serta antarmuka. Praktik ini didasarkan pada penggunaan abstraksi - mengisolasi perilaku dan properti umum dan memasukkannya ke dalam kelas abstrak, atau hanya mengisolasi perilaku umum - dalam hal ini kita membuat antarmuka. Membangun dan mendesain hierarki objek berdasarkan antarmuka dan pewarisan kelas merupakan prasyarat untuk memenuhi prinsip polimorfisme OOP. Mengenai masalah polimorfisme dan inovasi di Java, kami dapat menyebutkan bahwa saat membuat kelas dan antarmuka abstrak, dimulai dengan Java 8, dimungkinkan untuk menulis implementasi default metode abstrak di kelas dasar menggunakan kata kunci default. Misalnya:
public interface Swim {
    default void swim() {
        System.out.println("Just floating");
    }
}
Kadang-kadang mereka bertanya tentang persyaratan untuk mendeklarasikan metode di kelas dasar agar prinsip polimorfisme tidak dilanggar. Semuanya sederhana di sini: metode ini tidak boleh static , private dan final . Pribadi membuat metode hanya tersedia di kelas, dan Anda tidak dapat menimpanya di turunan. Statis menjadikan metode sebagai milik kelas, bukan objeknya, sehingga metode superkelas akan selalu dipanggil. Final akan membuat metode tersebut tidak dapat diubah dan disembunyikan dari ahli warisnya.

Apa yang diberikan polimorfisme kepada kita di Java?

Pertanyaan tentang apa yang diberikan penggunaan polimorfisme kepada kita kemungkinan besar juga akan muncul. Di sini Anda dapat menjawab secara singkat, tanpa membahas terlalu jauh:
  1. Memungkinkan Anda mengganti implementasi objek. Inilah yang menjadi dasar pengujian.
  2. Memberikan perluasan program - menjadi lebih mudah untuk menciptakan landasan bagi masa depan. Menambahkan tipe baru berdasarkan tipe yang sudah ada adalah cara paling umum untuk memperluas fungsionalitas program yang ditulis dalam gaya OOP.
  3. Memungkinkan Anda menggabungkan objek dengan tipe atau perilaku umum ke dalam satu koleksi atau larik dan memanipulasinya secara seragam (seperti dalam contoh kita, membuat semua orang menari - suatu metode danceatau berenang - suatu metode swim).
  4. Fleksibilitas saat membuat tipe baru: Anda dapat memilih untuk mengimplementasikan metode dari induk atau menimpanya pada anak.

Kata perpisahan untuk perjalanan

Prinsip polimorfisme merupakan topik yang sangat penting dan luas. Ini mencakup hampir setengah dari OOP Java dan sebagian besar dasar-dasar bahasa tersebut. Anda tidak akan bisa mendefinisikan prinsip ini dalam sebuah wawancara. Ketidaktahuan atau kesalahpahaman kemungkinan besar akan mengakhiri wawancara. Oleh karena itu, jangan malas untuk mengecek pengetahuan Anda sebelum ujian dan menyegarkannya jika perlu.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION