JavaRush /Java Blog /Random-ID /Merancang Kelas dan Antarmuka (Terjemahan artikel)
fatesha
Level 22

Merancang Kelas dan Antarmuka (Terjemahan artikel)

Dipublikasikan di grup Random-ID
Merancang Kelas dan Antarmuka (Terjemahan artikel) - 1

Isi

  1. Perkenalan
  2. Antarmuka
  3. Penanda antarmuka
  4. Antarmuka fungsional, metode statis, dan metode default
  5. Kelas abstrak
  6. Kelas yang tidak dapat diubah (permanen).
  7. Kelas anonim
  8. Visibilitas
  9. Warisan
  10. Warisan berganda
  11. Warisan dan komposisi
  12. Enkapsulasi
  13. Kelas dan metode terakhir
  14. Apa berikutnya
  15. Unduh kode sumber

1. PERKENALAN

Apa pun bahasa pemrograman yang Anda gunakan (tidak terkecuali Java), mengikuti prinsip desain yang baik adalah kunci untuk menulis kode yang bersih, mudah dipahami, dan dapat diverifikasi; dan juga membuatnya berumur panjang dan mudah mendukung penyelesaian masalah. Pada bagian tutorial ini, kita akan membahas elemen dasar yang disediakan oleh bahasa Java dan memperkenalkan beberapa prinsip desain dalam upaya membantu Anda membuat keputusan desain yang lebih baik. Lebih khusus lagi, kita akan membahas antarmuka dan antarmuka menggunakan metode default (fitur baru di Java 8), kelas abstrak dan final, kelas yang tidak dapat diubah, pewarisan, komposisi, dan meninjau kembali aturan visibilitas (atau aksesibilitas) yang telah kita bahas secara singkat di dalam Bagian 1 pelajaran "Cara membuat dan menghancurkan benda" .

2. ANTARMUKA

Dalam pemrograman berorientasi objek , konsep antarmuka menjadi dasar pengembangan kontrak . Singkatnya, antarmuka menentukan sekumpulan metode (kontrak) dan setiap kelas yang memerlukan dukungan untuk antarmuka spesifik tersebut harus menyediakan implementasi metode tersebut: sebuah ide yang cukup sederhana namun kuat. Banyak bahasa pemrograman memiliki antarmuka dalam satu atau lain bentuk, tetapi Java khususnya menyediakan dukungan bahasa untuk ini. Mari kita lihat definisi antarmuka sederhana di Java.
package com.javacodegeeks.advanced.design;

public interface SimpleInterface {
void performAction();
}
Dalam cuplikan di atas, antarmuka yang kita panggil SimpleInterface, hanya mendeklarasikan satu metode yang disebut performAction. Perbedaan utama antara antarmuka dan kelas adalah bahwa antarmuka menguraikan kontak yang seharusnya (mereka mendeklarasikan suatu metode), tetapi tidak menyediakan implementasinya. Namun, antarmuka di Java bisa lebih kompleks: antarmuka dapat mencakup antarmuka bersarang, kelas, jumlah, anotasi, dan konstanta. Misalnya:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefinitions {
    String CONSTANT = "CONSTANT";

    enum InnerEnum {
        E1, E2;
    }

    class InnerClass {
    }

    interface InnerInterface {
        void performInnerAction();
    }

    void performAction();
}
Dalam contoh yang lebih kompleks ini, ada beberapa batasan yang diterapkan tanpa syarat oleh antarmuka pada konstruksi bersarang dan deklarasi metode, dan ini diterapkan oleh kompiler Java. Pertama-tama, meskipun tidak dideklarasikan secara eksplisit, setiap deklarasi metode dalam antarmuka bersifat publik (dan hanya dapat bersifat publik). Jadi deklarasi metode berikut ini setara:
public void performAction();
void performAction();
Perlu disebutkan bahwa setiap metode dalam antarmuka secara implisit dideklarasikan abstract , dan bahkan deklarasi metode ini pun setara:
public abstract void performAction();
public void performAction();
void performAction();
Sedangkan untuk bidang konstanta yang dideklarasikan, selain bersifat public , bidang tersebut juga secara implisit static dan ditandai final . Oleh karena itu, deklarasi berikut juga setara:
String CONSTANT = "CONSTANT";
public static final String CONSTANT = "CONSTANT";
Terakhir, kelas, antarmuka, atau jumlah yang disarangkan, selain bersifat public , juga secara implisit dideklarasikan static . Misalnya, deklarasi ini juga setara dengan:
class InnerClass {
}

static class InnerClass {
}
Gaya yang Anda pilih adalah preferensi pribadi, namun mengetahui properti antarmuka sederhana ini dapat menyelamatkan Anda dari pengetikan yang tidak perlu.

3. Penanda antarmuka

Antarmuka penanda adalah jenis antarmuka khusus yang tidak memiliki metode atau konstruksi bersarang lainnya. Bagaimana perpustakaan Java mendefinisikannya:
public interface Cloneable {
}
Penanda antarmuka bukanlah kontrak semata, tetapi merupakan teknik yang berguna untuk "melampirkan" atau "mengaitkan" beberapa sifat tertentu dengan suatu kelas. Misalnya, sehubungan dengan Cloneable , kelas ditandai sebagai dapat dikloning, namun cara penerapannya bukan merupakan bagian dari antarmuka. Contoh penanda antarmuka lain yang sangat terkenal dan banyak digunakan adalah Serializable:
public interface Serializable {
}
Antarmuka ini menandai kelas yang sesuai untuk serialisasi dan deserialisasi, dan sekali lagi, antarmuka ini tidak menentukan bagaimana hal ini dapat atau harus diimplementasikan. Penanda antarmuka memiliki tempatnya dalam pemrograman berorientasi objek, meskipun penanda tersebut tidak memenuhi tujuan utama antarmuka sebagai kontrak. 

4. ANTARMUKA FUNGSIONAL, METODE DEFAULT DAN METODE STATIS

Sejak rilis Java 8, antarmuka telah memperoleh beberapa fitur baru yang sangat menarik: metode statis, metode default, dan konversi otomatis dari lambda (antarmuka fungsional). Di bagian antarmuka, kami menekankan fakta bahwa antarmuka di Java hanya dapat mendeklarasikan metode, tetapi tidak menyediakan implementasinya. Dengan metode default, segalanya berbeda: antarmuka dapat menandai metode dengan kata kunci default dan menyediakan implementasinya. Misalnya:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefaultMethods {
    void performAction();

    default void performDefaulAction() {
        // Implementation here
    }
}
Berada di tingkat instance, metode default dapat ditimpa oleh setiap implementasi antarmuka, namun antarmuka sekarang juga dapat menyertakan metode statis , misalnya: package com.javacodegeeks.advanced.design;
public interface InterfaceWithDefaultMethods {
    static void createAction() {
        // Implementation here
    }
}
Dapat dikatakan bahwa menyediakan implementasi di antarmuka menggagalkan seluruh tujuan pemrograman kontrak. Namun ada banyak alasan mengapa fitur-fitur ini diperkenalkan ke dalam bahasa Java dan betapapun berguna atau membingungkannya, fitur-fitur tersebut tersedia untuk Anda dan Anda gunakan. Antarmuka fungsional memiliki cerita yang berbeda dan telah terbukti menjadi tambahan yang sangat berguna pada bahasa ini. Pada dasarnya, antarmuka fungsional adalah antarmuka yang hanya mendeklarasikan satu metode abstrak di dalamnya. RunnableAntarmuka perpustakaan standar adalah contoh yang sangat bagus dari konsep ini.
@FunctionalInterface
public interface Runnable {
    void run();
}
Kompiler Java memperlakukan antarmuka fungsional secara berbeda dan dapat mengubah fungsi lambda menjadi implementasi antarmuka fungsional jika masuk akal. Mari kita perhatikan deskripsi fungsi berikut: 
public void runMe( final Runnable r ) {
    r.run();
}
Untuk memanggil fungsi ini di Java 7 dan di bawahnya, implementasi antarmuka harus disediakan Runnable(misalnya menggunakan kelas anonim), namun di Java 8 cukup menyediakan implementasi metode run() menggunakan sintaks lambda:
runMe( () -> System.out.println( "Run!" ) );
Selain itu, anotasi @FunctionalInterface (anotasi akan dibahas secara rinci di Bagian 5 tutorial) mengisyaratkan bahwa kompiler dapat memeriksa apakah suatu antarmuka hanya berisi satu metode abstrak, sehingga perubahan apa pun yang dilakukan pada antarmuka di masa mendatang tidak akan melanggar asumsi ini .

5. KELAS ABSTRAK

Konsep menarik lainnya yang didukung oleh bahasa Java adalah konsep kelas abstrak. Kelas abstrak agak mirip dengan antarmuka di Java 7 dan sangat mirip dengan antarmuka metode default di Java 8. Tidak seperti kelas biasa, kelas abstrak tidak dapat dipakai, tetapi dapat dibuat subkelasnya (lihat bagian Warisan untuk lebih jelasnya). Lebih penting lagi, kelas abstrak dapat berisi metode abstrak: jenis metode khusus tanpa implementasi, seperti antarmuka. Misalnya:
package com.javacodegeeks.advanced.design;

public abstract class SimpleAbstractClass {
    public void performAction() {
        // Implementation here
    }

    public abstract void performAnotherAction();
}
Dalam contoh ini, kelas SimpleAbstractClassdideklarasikan sebagai abstrak dan berisi satu metode abstrak yang dideklarasikan. Kelas abstrak sangat berguna; sebagian besar atau bahkan beberapa bagian dari detail implementasi dapat dibagikan ke banyak subkelas. Meskipun demikian, mereka tetap membiarkan pintunya terbuka dan memungkinkan Anda untuk menyesuaikan perilaku yang melekat pada setiap subkelas menggunakan metode abstrak. Perlu disebutkan bahwa tidak seperti antarmuka, yang hanya dapat berisi deklarasi publik , kelas abstrak dapat menggunakan kekuatan penuh aturan aksesibilitas untuk mengontrol visibilitas metode abstrak.

6. KELAS SEGERA

Kekekalan menjadi semakin penting dalam pengembangan perangkat lunak saat ini. Munculnya sistem multi-inti telah menimbulkan banyak masalah terkait berbagi data dan paralelisme. Namun satu masalah pasti muncul: memiliki sedikit (atau bahkan tidak ada) keadaan yang dapat diubah akan menghasilkan ekstensibilitas (skalabilitas) yang lebih baik dan penalaran yang lebih mudah tentang sistem. Sayangnya, bahasa Java tidak memberikan dukungan yang layak untuk kekekalan kelas. Namun, dengan menggunakan kombinasi teknik, dimungkinkan untuk merancang kelas yang tidak dapat diubah. Pertama-tama, semua bidang kelas harus final (ditandai sebagai final ). Ini merupakan awal yang baik, namun bukan jaminan. 
package com.javacodegeeks.advanced.design;

import java.util.Collection;

public class ImmutableClass {
    private final long id;
    private final String[] arrayOfStrings;
    private final Collection<String> collectionOfString;
}
Kedua, pastikan inisialisasi yang tepat: jika suatu bidang adalah referensi ke koleksi atau larik, jangan tetapkan bidang tersebut langsung dari argumen konstruktor, melainkan buatlah salinannya. Ini akan memastikan bahwa status koleksi atau larik tidak diubah di luarnya.
public ImmutableClass( final long id, final String[] arrayOfStrings,
        final Collection<String> collectionOfString) {
    this.id = id;
    this.arrayOfStrings = Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
    this.collectionOfString = new ArrayList<>( collectionOfString );
}
Dan terakhir, memastikan akses yang tepat (pengambil). Untuk koleksi, kekekalan harus disediakan sebagai pembungkus  Collections.unmodifiableXxx: Dengan array, satu-satunya cara untuk memberikan kekekalan yang sebenarnya adalah dengan menyediakan salinan alih-alih mengembalikan referensi ke array. Hal ini mungkin tidak dapat diterima dari sudut pandang praktis, karena sangat bergantung pada ukuran susunan dan dapat memberikan tekanan yang sangat besar pada pengumpul sampah.
public String[] getArrayOfStrings() {
    return Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
}
Bahkan contoh kecil ini memberikan gambaran bagus bahwa kekekalan belum menjadi warga negara kelas satu di Jawa. Segalanya bisa menjadi rumit jika kelas yang tidak dapat diubah memiliki bidang yang merujuk ke objek kelas lain. Kelas-kelas tersebut juga harusnya tidak dapat diubah, tetapi tidak ada cara untuk memastikan hal ini. Ada beberapa penganalisis kode sumber Java yang layak, seperti FindBugs dan PMD, yang dapat sangat membantu dengan memeriksa kode Anda dan menunjukkan kelemahan umum pemrograman Java. Alat-alat ini adalah teman baik bagi pengembang Java mana pun.

7. KELAS ANONIM

Di era sebelum Java 8, kelas anonim adalah satu-satunya cara untuk memastikan kelas ditentukan dengan cepat dan dipakai dengan segera. Tujuan dari kelas anonim adalah untuk mengurangi boilerplate dan menyediakan cara singkat dan mudah untuk mewakili kelas sebagai catatan. Mari kita lihat cara kuno untuk membuat thread baru di Java:
package com.javacodegeeks.advanced.design;

public class AnonymousClass {
    public static void main( String[] args ) {
        new Thread(
            // Example of creating anonymous class which implements
            // Runnable interface
            new Runnable() {
                @Override
                public void run() {
                    // Implementation here
                }
            }
        ).start();
    }
}
Dalam contoh ini, implementasi Runnableantarmuka disediakan langsung sebagai kelas anonim. Meskipun ada beberapa keterbatasan yang terkait dengan kelas anonim, kelemahan utama penggunaannya adalah sintaksis konstruksi yang sangat verbose yang diwajibkan oleh bahasa Java. Bahkan kelas anonim yang tidak melakukan apa pun memerlukan setidaknya 5 baris kode setiap kali ditulis.
new Runnable() {
   @Override
   public void run() {
   }
}
Untungnya, dengan Java 8, lambda, dan antarmuka fungsional, semua stereotip ini akan segera hilang, dan akhirnya penulisan kode Java akan terlihat sangat ringkas.
package com.javacodegeeks.advanced.design;

public class AnonymousClass {
    public static void main( String[] args ) {
        new Thread( () -> { /* Implementation here */ } ).start();
    }
}

8. VISIBILITAS

Kita sudah membicarakan sedikit tentang aturan visibilitas dan aksesibilitas di Java di Bagian 1 tutorial. Pada bagian ini, kita akan meninjau kembali topik ini lagi, namun dalam konteks subkelas. Merancang Kelas dan Antarmuka (Terjemahan artikel) - 2Visibilitas pada tingkat yang berbeda memungkinkan atau mencegah kelas melihat kelas atau antarmuka lain (misalnya, jika mereka berada dalam paket berbeda atau bersarang satu sama lain) atau subkelas melihat dan mengakses metode, konstruktor, dan bidang induknya. Di bagian selanjutnya, warisan, kita akan melihat cara kerjanya.

9. WARISAN

Warisan adalah salah satu konsep kunci pemrograman berorientasi objek, yang berfungsi sebagai dasar untuk membangun hubungan kelas. Dikombinasikan dengan aturan visibilitas dan aksesibilitas, pewarisan memungkinkan kelas dirancang menjadi hierarki yang dapat diperluas dan dipelihara. Pada tingkat konseptual, pewarisan di Java diimplementasikan menggunakan subkelas dan kata kunci extends , bersama dengan kelas induk. Subkelas mewarisi semua elemen publik dan dilindungi dari kelas induk. Selain itu, subkelas mewarisi elemen paket-pribadi dari kelas induknya jika keduanya (subkelas dan kelas) berada dalam paket yang sama. Meskipun demikian, sangat penting, apa pun yang Anda coba desain, untuk tetap berpegang pada serangkaian metode minimum yang diekspos oleh suatu kelas secara publik atau pada subkelasnya. Misalnya, mari kita lihat kelas Parentdan subkelasnya Childuntuk menunjukkan perbedaan tingkat visibilitas dan pengaruhnya.
package com.javacodegeeks.advanced.design;

public class Parent {
    // Everyone can see it
    public static final String CONSTANT = "Constant";

    // No one can access it
    private String privateField;
    // Only subclasses can access it
    protected String protectedField;

    // No one can see it
    private class PrivateClass {
    }

    // Only visible to subclasses
    protected interface ProtectedInterface {
    }

    // Everyone can call it
    public void publicAction() {
    }

    // Only subclass can call it
    protected void protectedAction() {
    }

    // No one can call it
    private void privateAction() {
    }

    // Only subclasses in the same package can call it
    void packageAction() {
    }
}
package com.javacodegeeks.advanced.design;

// Resides in the same package as parent class
public class Child extends Parent implements Parent.ProtectedInterface {
    @Override
    protected void protectedAction() {
        // Calls parent's method implementation
        super.protectedAction();
    }

    @Override
    void packageAction() {
        // Do nothing, no call to parent's method implementation
    }

    public void childAction() {
        this.protectedField = "value";
    }
}
Warisan adalah topik yang sangat besar, dengan banyak detail khusus untuk Java. Namun, ada beberapa aturan yang mudah diikuti dan dapat membantu menjaga singkatnya hierarki kelas. Di Java, setiap subkelas dapat mengganti metode apa pun yang diwarisi dari induknya kecuali jika metode tersebut telah dinyatakan final. Namun, tidak ada sintaks atau kata kunci khusus untuk menandai suatu metode sebagai diganti, yang dapat menyebabkan kebingungan. Inilah sebabnya mengapa anotasi @Override diperkenalkan : setiap kali tujuan Anda adalah mengganti metode yang diwariskan, harap gunakan anotasi @Override untuk menunjukkannya secara ringkas. Dilema lain yang selalu dihadapi pengembang Java dalam desain adalah konstruksi hierarki kelas (dengan kelas konkret atau abstrak) versus implementasi antarmuka. Kami sangat menyarankan untuk memilih antarmuka daripada kelas atau kelas abstrak bila memungkinkan. Antarmuka lebih ringan, lebih mudah untuk diuji dan dipelihara, dan juga meminimalkan efek samping dari perubahan implementasi. Banyak teknik pemrograman tingkat lanjut, seperti membuat kelas proxy di perpustakaan standar Java, sangat bergantung pada antarmuka.

10. WARISAN GANDA

Tidak seperti C++ dan beberapa bahasa lainnya, Java tidak mendukung pewarisan berganda: di Java, setiap kelas hanya dapat memiliki satu induk langsung (dengan kelas Objectberada di puncak hierarki). Namun, sebuah kelas dapat mengimplementasikan banyak antarmuka, dan dengan demikian penumpukan antarmuka adalah satu-satunya cara untuk mencapai (atau mensimulasikan) banyak warisan di Java.
package com.javacodegeeks.advanced.design;

public class MultipleInterfaces implements Runnable, AutoCloseable {
    @Override
    public void run() {
        // Some implementation here
    }

    @Override
    public void close() throws Exception {
       // Some implementation here
    }
}
Mengimplementasikan banyak antarmuka sebenarnya cukup ampuh, namun sering kali kebutuhan untuk menggunakan implementasi berulang kali mengarah pada hierarki kelas yang mendalam sebagai cara untuk mengatasi kurangnya dukungan Java untuk pewarisan berganda. 
public class A implements Runnable {
    @Override
    public void run() {
        // Some implementation here
    }
}
// Class B wants to inherit the implementation of run() method from class A.
public class B extends A implements AutoCloseable {
    @Override
    public void close() throws Exception {
       // Some implementation here
    }
}
// Class C wants to inherit the implementation of run() method from class A
// and the implementation of close() method from class B.
public class C extends B implements Readable {
    @Override
    public int read(java.nio.CharBuffer cb) throws IOException {
       // Some implementation here
    }
}
Dan seterusnya... Rilis terbaru Java 8 mengatasi masalah dengan injeksi metode default. Karena metode default, antarmuka sebenarnya tidak hanya menyediakan kontrak, tetapi juga implementasi. Oleh karena itu, kelas yang mengimplementasikan antarmuka ini juga akan secara otomatis mewarisi metode yang diimplementasikan tersebut. Misalnya:
package com.javacodegeeks.advanced.design;

public interface DefaultMethods extends Runnable, AutoCloseable {
    @Override
    default void run() {
        // Some implementation here
    }

    @Override
    default void close() throws Exception {
       // Some implementation here
    }
}

// Class C inherits the implementation of run() and close() methods from the
// DefaultMethods interface.
public class C implements DefaultMethods, Readable {
    @Override
    public int read(java.nio.CharBuffer cb) throws IOException {
       // Some implementation here
    }
}
Ingatlah bahwa pewarisan berganda adalah alat yang sangat ampuh namun sekaligus berbahaya. Masalah Diamond of Death yang terkenal sering disebut-sebut sebagai kelemahan utama dalam penerapan pewarisan berganda, sehingga memaksa pengembang untuk merancang hierarki kelas dengan sangat hati-hati. Sayangnya, antarmuka Java 8 dengan metode default juga menjadi korban cacat ini.
interface A {
    default void performAction() {
    }
}

interface B extends A {
    @Override
    default void performAction() {
    }
}

interface C extends A {
    @Override
    default void performAction() {
    }
}
Misalnya, cuplikan kode berikut akan gagal dikompilasi:
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
Pada titik ini, wajar untuk mengatakan bahwa Java sebagai sebuah bahasa selalu berusaha menghindari kasus-kasus sudut pemrograman berorientasi objek, namun seiring dengan berkembangnya bahasa, beberapa kasus tersebut tiba-tiba mulai muncul. 

11. WARISAN DAN KOMPOSISI

Untungnya, pewarisan bukanlah satu-satunya cara untuk mendesain kelas Anda. Alternatif lain yang diyakini banyak pengembang jauh lebih baik daripada warisan adalah komposisi. Idenya sangat sederhana: alih-alih membuat hierarki kelas, kelas harus terdiri dari kelas lain. Mari kita lihat contoh ini:
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
Kelasnya Vehicleterdiri dari mesin dan roda (ditambah banyak bagian lain yang dikesampingkan demi kesederhanaan). Namun dapat dikatakan bahwa suatu kelas Vehiclejuga merupakan sebuah mesin, sehingga dapat dirancang dengan menggunakan pewarisan. 
public class Vehicle extends Engine {
    private Wheels[] wheels;
    // ...
}
Solusi desain mana yang benar? Pedoman inti umum tersebut dikenal dengan prinsip IS-A (is) dan HAS-A (contains). IS-A adalah hubungan pewarisan: subkelas juga memenuhi spesifikasi kelas dari kelas induk dan variasi dari kelas induk. subkelas) memperluas induknya. Jika Anda ingin mengetahui apakah satu entitas memperluas entitas lainnya, lakukan uji kecocokan - IS -A (is).") Oleh karena itu, HAS-A adalah hubungan komposisi: kelas memiliki (atau berisi) objek yang Dalam kebanyakan kasus, prinsip HAS-A bekerja lebih baik daripada IS-A karena sejumlah alasan: 
  • Desain lebih fleksibel;
  • Model ini lebih stabil karena perubahan tidak menyebar melalui hierarki kelas;
  • Sebuah kelas dan komposisinya dipasangkan secara longgar dibandingkan dengan komposisi yang memasangkan erat induk dan subkelasnya.
  • Alur pemikiran logis dalam sebuah kelas lebih sederhana, karena semua dependensinya disertakan di dalamnya, di satu tempat. 
Terlepas dari itu, pewarisan mempunyai tempatnya dan menyelesaikan sejumlah masalah desain yang ada dengan berbagai cara, sehingga tidak boleh diabaikan. Harap ingat kedua alternatif ini saat merancang model berorientasi objek Anda.

12. ENKAPSULASI.

Konsep enkapsulasi dalam pemrograman berorientasi objek adalah menyembunyikan semua detail implementasi (seperti mode operasi, metode internal, dll.) dari dunia luar. Keuntungan enkapsulasi adalah pemeliharaan dan kemudahan perubahan. Implementasi internal kelas disembunyikan, bekerja dengan data kelas terjadi secara eksklusif melalui metode publik kelas (masalah nyata jika Anda mengembangkan perpustakaan atau kerangka kerja yang digunakan oleh banyak orang). Enkapsulasi di Java dicapai melalui aturan visibilitas dan aksesibilitas. Di Java, praktik terbaiknya adalah tidak pernah mengekspos bidang secara langsung, hanya melalui pengambil dan penyetel (kecuali bidang tersebut ditandai sebagai final). Misalnya:
package com.javacodegeeks.advanced.design;

public class Encapsulation {
    private final String email;
    private String address;

    public Encapsulation( final String email ) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }
}
Contoh ini mengingatkan pada apa yang disebut JavaBeans dalam bahasa Java: kelas Java standar ditulis berdasarkan sekumpulan konvensi, salah satunya mengizinkan bidang diakses hanya menggunakan metode pengambil dan penyetel. Seperti yang sudah kami tekankan di bagian pewarisan, harap selalu mematuhi kontrak publisitas minimum di suatu kelas, dengan menggunakan prinsip enkapsulasi. Segala sesuatu yang tidak boleh bersifat publik harus menjadi pribadi (atau dilindungi/dipaketkan pribadi, tergantung pada masalah yang Anda pecahkan). Hal ini akan membuahkan hasil dalam jangka panjang dengan memberi Anda kebebasan mendesain tanpa (atau setidaknya meminimalkan) perubahan yang mengganggu. 

13. KELAS DAN METODE AKHIR

Di Java, ada cara untuk mencegah suatu kelas menjadi subkelas dari kelas lain: kelas lain tersebut harus dinyatakan final. 
package com.javacodegeeks.advanced.design;

public final class FinalClass {
}
Kata kunci final yang sama dalam deklarasi metode mencegah subkelas menimpa metode tersebut. 
package com.javacodegeeks.advanced.design;

public class FinalMethod {
    public final void performAction() {
    }
}
Tidak ada aturan umum untuk memutuskan apakah suatu kelas atau metode harus final atau tidak. Kelas dan metode akhir membatasi ekstensibilitas dan sangat sulit untuk berpikir ke depan apakah suatu kelas harus diwarisi atau tidak, atau apakah suatu metode harus ditimpa atau tidak di masa mendatang. Hal ini sangat penting bagi pengembang perpustakaan, karena keputusan desain seperti ini dapat membatasi penerapan perpustakaan secara signifikan. Perpustakaan Standar Java memiliki beberapa contoh kelas akhir, yang paling terkenal adalah kelas String. Pada tahap awal, keputusan ini dibuat untuk mencegah segala upaya pengembang untuk menemukan solusi mereka sendiri yang “lebih baik” untuk mengimplementasikan string. 

14. APA SELANJUTNYA

Pada bagian pelajaran ini, kita membahas konsep pemrograman berorientasi objek di Java. Kami juga melihat sekilas pemrograman kontrak, menyentuh beberapa konsep fungsional dan melihat bagaimana bahasa tersebut berkembang seiring waktu. Di bagian selanjutnya dari pelajaran ini, kita akan bertemu dengan obat generik dan bagaimana obat generik mengubah cara kita mendekati keamanan tipe dalam pemrograman. 

15. UNDUH KODE SUMBER

Anda dapat mengunduh sumbernya di sini - advanced-java-part-3 Sumber: Cara mendesain Kelas an
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION