Mengapa seorang pembangun harus kelas dalam daripada di file kelasnya sendiri?

24

Banyak Builder Patterncontoh membuat Builderkelas batin dari objek yang dibangunnya.

Ini masuk akal karena ini menunjukkan apa yang Buildermembangun. Namun, dalam bahasa yang diketik secara statis kita tahu apa yang Buildermembangun.

Di sisi lain jika itu Builderadalah kelas batin, Anda harus tahu kelas apa yang Builderdibangun tanpa melihat ke dalam Builder.

Juga, menjadikan pembangun sebagai kelas dalam mengurangi jumlah impor karena dapat dirujuk oleh kelas luar - jika Anda peduli tentang itu.

Dan kemudian ada contoh-contoh praktis di mana paket itu Builderberada dalam paket yang sama, tetapi bukan kelas dalam, seperti StringBuilder. Anda tahu bahwa Builder harus membangun Stringkarena dinamai demikian.

Yang sedang berkata, satu-satunya alasan bagus yang dapat saya pikirkan untuk membuat Builderkelas dalam adalah bahwa Anda tahu apa kelas Builderitu tanpa mengetahui namanya atau mengandalkan konvensi penamaan. Sebagai contoh, jika StringBuilderkelas dalam Stringsaya mungkin akan tahu itu ada lebih cepat daripada yang saya lakukan (spekulatif).

Apakah ada alasan lain untuk menjadikan Builderkelas batin atau hanya karena preferensi dan ritual?

Nathanial
sumber

Jawaban:

30

Saya pikir alasan untuk melakukan ini adalah agar kelas dalam (Builder) dapat mengakses anggota kelas yang sedang dibangun.

Dari http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

Kelas bersarang non-statis (kelas dalam) memiliki akses ke anggota lain dari kelas terlampir, bahkan jika mereka dinyatakan pribadi.

...

Pertimbangkan dua kelas tingkat atas, A dan B, di mana B membutuhkan akses ke anggota A yang dinyatakan pribadi. Dengan menyembunyikan kelas B di dalam kelas A, anggota A dapat dinyatakan pribadi dan B dapat mengaksesnya.

...

Seperti metode instan dan variabel, kelas dalam dikaitkan dengan turunan dari kelas penutupnya dan memiliki akses langsung ke metode dan bidang objek itu.

Berikut beberapa kode untuk mencoba mengilustrasikan ini:

class Example {

    private int x;

    public int getX() { return this.x; }

    public static class Builder {

        public Example Create() {
            Example instance = new Example();
            instance.x = 5; // Builder can access Example's private member variable
            return instance;
        }
    }
}

Sebagai kelas statis, Builder tidak memiliki instance Contoh yang terkait dengannya. Namun, dengan memberikan instance dari Contoh (atau yang ia buat sendiri) Builder masih dapat mengakses anggota pribadi dari instance itu.

Apprentice Dr. Wily
sumber
Jawaban yang bagus, itu masuk akal! Namun pola pembangun biasanya memiliki kelas dalam statis dan hanya akan dapat mengakses anggota pribadi statis dari kelas luar. Jika Anda memiliki pembangun untuk kelas instan yang akan menjadi semua jenis aneh.
Nathanial
1
@Nathanial tidak sama sekali, variabel instance pribadi juga dapat diakses: ideone.com/7DyjDR
amon
1
@nathanial: Ya, tetapi pembangun tidak memanipulasi kelas; itu memanipulasi objek kelas yang pembangun itu sendiri telah instantiated.
Robert Harvey
@amon Saya melihat apa yang Anda lakukan di sana. Terima kasih untuk penjelasannya!
Nathanial
Secara khusus, ini memberikan akses pembangun ke konstruktor pribadi untuk kelas yang sedang dibangun, yang memungkinkan kelas menjadi abadi (semua bidang final) dan hanya instantiable melalui pembangun.
Matthew McPeak
1

Tidak ada "harus" dalam kasus ini. Mendefinisikan pembangun di dalam kelas lain atau memisahkannya adalah ortogonal dengan pola Builder. Banyak contoh melakukan ini karena kemudahan penyajian kode dalam satu file yang konsisten (juga untuk mengakses anggota pribadi tetapi itu tergantung pada konteksnya juga). Jangan ragu untuk melakukan sebaliknya

AZ01
sumber
Tidak yakin mengapa jawaban ini tidak dipilih, karena alasan lain selain, "karena kami tidak melakukannya di Jawa." Pola Builder menyediakan pembungkus di sekitar konstruktor yang mengambil banyak parameter. Jika konstruktor mengambil parameter tersebut, maka objek Builder tidak perlu mengakses anggota pribadi.
Greg Burghardt