Dilindungi di Antarmuka


111

Mengapa semua metode dalam interfacedefinisi secara implisit public? Mengapa tidak mengizinkan protectedmetode?


22
Pertanyaan yang sangat bagus. Untuk hampir semua hal lainnya di Jawa saya telah menemukan alasan sebenarnya untuk pilihan yang dibuat, tetapi untuk yang ini saya belum. Sangat masuk akal bagi saya untuk mendefinisikan metode yang dilindungi dalam antarmuka yang memungkinkan kelas lain di dalam paket yang sama untuk menggunakan metode ini pada objek implementasi tanpa perlu mengekspos metode itu, yang mungkin tidak dimaksudkan untuk dipanggil oleh orang lain selain dari anggota paket, ke seluruh dunia.
Markus A.

4
@Tokopedia Tetapi antarmuka bekerja dua arah, yaitu mereka juga dapat diimplementasikan oleh kelas di luar paket saat ini (dan kemudian mungkin diteruskan sebagai argumen ke metode di dalam paket ini). Bagaimana sebuah kelas dari luar paket saat ini dapat mengimplementasikan metode "dilindungi" dari beberapa antarmuka publik?
MartinStettner

8
@ MartinStettner: Itu tidak akan. Itulah intinya. Sebuah paket mungkin memiliki beberapa kelas yang tidak terkait yang mengimplementasikan sebuah antarmuka, dan ingin menjamin kode apa pun yang menerima referensi dari tipe antarmuka tersebut bahwa ia akan berperilaku dengan cara tertentu. Jaminan semacam itu dapat dibuat lebih kuat jika kode luar dapat dicegah dari klaim untuk mengimplementasikan antarmuka sambil berperilaku dengan cara yang bertentangan dengan kontraknya.
supercat

1
@Tokopedia Anda mengangkat poin yang bagus, Anda harus dapat mencapainya dengan sistem modul Java 9
Nir Alfasi

1
jika antarmuka memiliki protectedmetode, semua kelas pelaksana akan dilihat sebagai sub-tipe dari antarmuka. dan semua kelas ini DAPAT mengakses metode yang dilindungi. bukankah itu membuat protectedkata kunci pada metode tidak berguna? selama kami tidak memiliki cara untuk membatasi siapa yang mengimplementasikan kata kunci yang dilindungi antarmuka ini pada metode tidak berguna. perbaiki saya jika saya salah!
Amarnath Harish

Jawaban:


67

Karena antarmuka seharusnya berarti "apa yang dapat Anda lihat dari luar kelas". Tidak masuk akal untuk menambahkan metode non-publik.


16
Tetapi mengapa tidak memiliki fungsi yang hanya anggota dari paket yang sama dengan antarmuka "dapat melihat dari luar kelas"? Saya memiliki beberapa kasus penggunaan di mana saya berharap untuk ini.
Markus A.

5
@Tokopedia Saya menyadari ini terlambat, tetapi kemudian Anda dapat membuat sepenuhnya abstract class, yang semuanya interface, dan menentukan akses apa pun yang Anda inginkan. Memang ini kehilangan manfaat dari beberapa implementasi yang ada interfacedi Java, tetapi secara jujur ​​membuat kontrak yang mematuhi batasan beberapa paket lain akan menjadi tidak dapat diuji dan membingungkan, karena Anda secara praktis tidak dapat mengakses metode implementasi Anda sendiri di luar paket itu .
pickypg

10
@pickypg Tetapi jika kelas yang akan mengimplementasikan antarmuka sudah memperluas kelas lain, Anda tidak dapat membuatnya memperluas kelas lain. Saya tidak akan merasa bingung untuk antarmuka yang hanya digunakan di dalam paket.
Flamma

24
@Raveline, -1, Ini menimbulkan pertanyaan "mengapa sebuah antarmuka berarti apa yang dapat Anda lihat dari luar kelas?" Java 8 sudah mengizinkan tubuh metode dalam antarmuka, jadi mengapa tidak mengizinkan metode abstrak yang dilindungi juga?
Pacerier

8
Saya sering membaca penjelasan ini, tapi itu IMHO salah. Antarmuka adalah semacam "protokol pertukaran standar", tidak peduli apakah berbicara tentang OOP, API komunikasi atau perangkat keras. Port USB di PC saya jelas merupakan antarmuka publik. Tetapi pin pada mainboard saya, yang berada di belakang casing yang terkunci, yang menyediakan akses ke port USB opsional jelas merupakan antarmuka yang "dilindungi". Lalu kami memiliki chip BIOS - yang juga merupakan antarmuka standar, tetapi tidak pernah dipublikasikan dengan cara apa pun, hanya beberapa perusahaan yang mengetahui detail persisnya secara pribadi. Jadi, tentu saja, antarmuka dapat memiliki visibilitas apa pun! Kenapa tidak di OOP?
Foo Bar

55

Meskipun alasan yang sering dikutip adalah bahwa "antarmuka menentukan API publik", menurut saya itu adalah penyederhanaan yang berlebihan. (Dan itu "berbau" logika melingkar juga.)

Tidak ada artinya memiliki antarmuka yang memiliki campuran pengubah akses; misalnya sebagian untuk umum dan sebagian dibatasi untuk kelas lain dalam paket yang sama dengan antarmuka. Bahkan, dalam beberapa kasus ini bisa berguna, IMO.

Sebenarnya, menurut saya bagian dari alasan di balik membuat anggota antarmuka menjadi publik secara implisit adalah karena itu membuat bahasa Java lebih sederhana :

  • Anggota antarmuka publik secara implisit lebih mudah ditangani oleh pemrogram. Berapa kali Anda melihat kode (kelas) di mana pengubah akses metode dipilih secara acak? Banyak programmer "biasa" yang kesulitan memahami cara terbaik untuk mengelola batasan abstraksi Java 1 . Menambahkan publik / dilindungi / paket-pribadi ke antarmuka membuatnya semakin sulit bagi mereka.

  • Anggota antarmuka publik secara implisit menyederhanakan spesifikasi bahasa ... dan karenanya menjadi tugas untuk penulis kompiler Java, dan orang-orang yang mengimplementasikan Reflection API.

Garis pemikiran bahwa "antarmuka mendefinisikan API publik" bisa dibilang merupakan konsekuensi (atau karakteristik) dari keputusan desain bahasa yang disederhanakan ... bukan sebaliknya. Namun pada kenyataannya, kedua garis pemikiran tersebut mungkin berkembang secara paralel di benak para desainer Java.

Bagaimanapun, tanggapan resmi terhadap RFE di JDK-8179193 memperjelas bahwa tim desain Java memutuskan 2 bahwa mengizinkan protectedantarmuka menambah kompleksitas untuk sedikit manfaat nyata. Kudos to @skomisa karena telah menemukan buktinya .

Bukti di RFE menyelesaikan masalah ini. Itulah alasan resmi mengapa itu belum ditambahkan.


1 - Tentu saja, programmer top-gun tidak mengalami kesulitan dengan hal-hal ini, dan mungkin menyukai palet fitur kontrol akses yang lebih kaya. Tapi, apa yang terjadi ketika kode mereka diserahkan kepada orang lain untuk dipertahankan?

2 - Anda mungkin tidak setuju dengan keputusan mereka atau alasan yang mereka nyatakan tapi itu bisa diperdebatkan.


21

Saya harus mengatakan bahwa pertanyaan ini telah dibuka kembali oleh pengenalan metode default di Java 8. Proyek yang saya kerjakan sekarang, mirip dengan sifat dasar antarmuka, dimaksudkan untuk maksud abstrak dari implementasi.

Ada beberapa kasus di mana saya dapat secara drastis menyederhanakan kode saya dengan metode "dilindungi default". Ternyata itu tidak benar-benar berfungsi, karena antarmuka masih menggunakan logika Java 7. Metode terlindungi normal tidak terlalu masuk akal, karena alasan yang disebutkan di atas; tetapi jika metode publik default memerlukan sumber daya tingkat rendah yang kemungkinan besar tidak akan berubah dan dapat disediakan oleh metode terlindungi, menurut saya memiliki pekerjaan "dilindungi default" tidak hanya akan mempertahankan kode yang lebih bersih, tetapi juga akan melindungi pengguna di masa mendatang dari pelanggaran yang tidak disengaja.

(Ini secara tragis tidak mengubah fakta bahwa saya masih perlu memperumit kode saya dengan abstrak yang tidak perlu; tetapi saya bermaksud untuk memasukkan permintaan fitur di Oracle.)


Saya setuju 100%. Kelas abstrak adalah alternatif yang masuk akal sebelum pengenalan metode default. Namun, keterbatasan yang mereka tempatkan pada beberapa warisan berarti bahwa mereka tidak sempurna. Antarmuka dengan metode default biasanya merupakan alternatif yang lebih baik di dunia> = JDK 1.8, tetapi karena mereka tidak dapat menyimpan status, mereka bergantung pada pendefinisian metode abstrak lainnya untuk mengekspos status, yang berarti bahwa status dibuat publik, yang tidak selalu seperti itu. kamu ingin.
Pastor Jeremy Krieg

10

Karena antarmuka menentukan API publik. Apa pun yang dilindungi adalah detail internal yang tidak termasuk dalam antarmuka.

Anda dapat menggunakan kelas abstrak dengan metode abstrak yang dilindungi, tetapi antarmuka dibatasi untuk metode publik dan kolom final statis publik.


5
Anda menyatakan "karena antarmuka menentukan API publik". Jadi apa alasan antarmuka hanya mendefinisikan publicAPI? Ada perbedaan antara "detail internal" dengan "detail implementasi", protecteddi Java jelas bukan detail internal karena sekarang antarmuka publik dipublikasikan untuk semua orang yang dapat membuat subkelasnya, yang pada dasarnya adalah seluruh dunia.
Pacerier

1
Tidak benar lagi dengan metode default Java 8.
Mario Rossi

@MarioRossi Dan juga tidak benar lagi dengan metode antarmuka pribadi Java 9.
skomisa

7

Mungkin, karena ini adalah antarmuka , yaitu ada di sana untuk memberi tahu klien apa yang dapat mereka lakukan dengan instance, daripada memberi tahu mereka apa yang tidak dapat mereka lakukan.


1
Saya tidak mengerti mengapa sebuah antarmuka juga tidak bisa memberi tahu subclass apa yang dapat mereka lakukan tanpa mengekspos implementasi itu ke dunia luar. Ini adalah keputusan desain yang dibuat pada saat kelas abstrak dapat digunakan sebagai alternatif yang sempurna. Tetapi dengan munculnya metode default di antarmuka, kelas abstrak sekarang menjadi alternatif yang tidak sempurna.
Pastor Jeremy Krieg

6

Saya sangat merasa bahwa antarmuka harus mengizinkan metode yang dilindungi; siapa bilang antarmuka harus terlihat oleh semua orang di seluruh dunia? Mengenai poin Anda yang mungkin membingungkan programmer "biasa" (baca: tidak kompeten): Begitu banyak OOP adalah tentang menyusun objek, kelas, paket, dll. Dengan benar, jika seorang programmer kesulitan melakukan semua itu dengan benar, dia memiliki masalah yang jauh lebih besar. Java dibangun untuk hal semacam itu.


Ini tidak menjawab pertanyaan itu.
Stephen C

5

Beberapa jawaban di sini menggunakan penalaran melingkar untuk menjelaskan mengapa metode antarmuka tidak dapat dilindungi: itu karena metode tersebut harus bersifat publik, jadi jelas mereka tidak dapat dilindungi!

Itu tidak menjelaskan apa-apa, tetapi untungnya seseorang mengajukan permintaan peningkatan untuk metode yang dilindungi di antarmuka sebagai bug JDK beberapa tahun yang lalu, yang menjelaskan masalah ini:

Metode yang dilindungi dalam antarmuka: berbagi antar paket

Karena pengubah agak terbatas di Java, cara untuk berbagi metode di seluruh paket dibatasi untuk metode publik. Terkadang berbahaya untuk membuat sebuah metode menjadi publik, tetapi itu perlu karena kurangnya pengubah yang tepat. Solusi saya mengatasi batasan ini.

Spesifikasi bahasa java saat ini tidak mengizinkan pengubah yang dilindungi untuk metode antarmuka. Kami dapat memanfaatkan fakta ini dan menggunakan metode antarmuka dilindungi untuk fitur baru ini.

Jika metode antarmuka ditandai dilindungi dan antarmuka diimplementasikan oleh kelas dalam paket lain, metode tersebut tidak perlu bersifat publik, tetapi bisa juga bersifat pribadi atau setidaknya dilindungi paket. Metode ini terlihat, apa pun yang dideklarasikan oleh kelas dan selain itu terlihat dalam paket sumber antarmuka (dan sub paket?).

Dengan cara ini kami dapat membagikan metode tertentu di seluruh paket terkenal.

Dan ini adalah respon dari permintaan peningkatan itu, yang ditutup dengan status Won't fix:

Proposal ini mencoba untuk memecahkan masalah dengan cara yang menambah kompleksitas dan kasus khusus untuk keuntungan aktual yang kecil. Cara khas untuk mengatasi masalah ini adalah memiliki kelas privat yang mengimplementasikan antarmuka publik. Metode implementasinya bersifat publik, tetapi dalam kelas privat, jadi metode tersebut tetap privat.

Alternatif yang tersedia mulai di Java 9 adalah membuat kelas dan metode menjadi publik, tetapi dalam modul yang memiliki ekspor-yang memenuhi syarat ke modul "teman" tertentu alih-alih diekspor ke publik umum.

Jadi kesimpulan resmi dari laporan bug itu adalah:

  • Situasi saat ini tidak akan berubah; antarmuka tidak mungkin mendukung protectedmetode.
  • Alasan untuk tidak mendukung protectedmetode dalam antarmuka adalah bahwa ia " menambah kompleksitas dan kasus khusus untuk keuntungan aktual yang kecil ".
  • Sejak Java 9 ada pendekatan alternatif untuk menyediakan akses tingkat paket ke metode. Gunakan Java Platform Module System (JPMS) untuk " membuat kelas dan metode menjadi publik, tetapi dalam modul yang memiliki ekspor-yang memenuhi syarat ke modul" teman "tertentu alih-alih diekspor ke publik umum ".

4

Karena kelas pelaksana harus mengimplementasikan SEMUA metode yang dideklarasikan di antarmuka Anda, apa yang akan terjadi jika kelas penerapan Anda berada dalam paket yang berbeda?


2

Antarmuka Jika Anda ingin menggunakan sesuatu seperti yang Anda jelaskan, lanjutkan dengan kelas abstrak atau antarmuka bersarang.

Kutipan dari Gaya Kode tentang variabel antarmuka, tetapi masih berlaku untuk metode:

Variabel antarmuka secara implisit bersifat publik karena antarmuka dimaksudkan untuk menyediakan Antarmuka Pemrograman Aplikasi (API) yang dapat diakses sepenuhnya oleh pemrogram Java untuk referensi dan diterapkan dalam aplikasi mereka sendiri. Karena antarmuka dapat digunakan dalam paket Java yang berbeda dari miliknya, visibilitas publik memastikan bahwa kode program dapat mengakses variabel.

2

Mendeklarasikan subinterfaces internal adalah praktik yang baik, tetapi Anda tidak dapat mendeklarasikan metode internal Anda seperti protectedpada antarmuka di Java, secara teknis.

Tentu saja, Anda dapat membuat antarmuka lain untuk penggunaan internal yang memperluas antarmuka publik:

package yourpackage;

public interface PublicInterface {

    public void doThing1();

    public void doThing2();

    public void doThing3();

}

package yourpackage;

interface InternalInterface extends PublicInterface {

    void doAnyInternalThing1();

    void doAnyInternalThing2();

}

Anda dapat menggunakan InternalInterfaceantarmuka di dalam paket, tetapi Anda harus menerima subtipe apa pun dari PublicInterface(dalam metode publik):

package yourpackage;

public class SomeClass {

    public void someMethod(PublicInterface param) {
        if (param instanceof InternalInterface) {
            // run the optimized code
        } else {
            // run the general code
        }
    }

}

Di luar paket pengguna dapat menggunakan PublicInterfacetanpa masalah.

Biasanya programmer membuat kelas abstrak dalam situasi serupa. Namun, dalam kasus ini kita kehilangan manfaat dari multiple inheritance.


1
Di luar paket, pengguna juga dapat menggunakan YourPublicInterface.Internal. Segala sesuatu dalam sebuah antarmuka, termasuk antarmuka bersarang, bersifat publik terlepas dari ada atau tidaknya publickata kunci.
Greg Roelofs

1

Satu-satunya skenario yang masuk akal adalah ketika Anda ingin membatasi visibilitas ke paket yang sama. Semua penggunaan lainnya protectedtidak berlaku. Secara khusus, protectedmetode sering digunakan untuk memberikan akses ke beberapa detail implementasi tingkat yang lebih rendah untuk turunan. Tetapi menyatakan itu dalam sebuah antarmuka tidak masuk akal, karena tidak ada implementasi tingkat yang lebih rendah untuk diekspos.

Dan bahkan skenario paket bukanlah tentang antarmuka.

Untuk mencapai apa yang mungkin Anda inginkan, Anda memerlukan dua antarmuka, satu untuk penggunaan internal dan satu lagi yang Anda tampilkan di API publik. (Dengan kemungkinan internal, tetapi tidak perlu memperluas yang publik.) Atau, seperti yang ditunjukkan orang lain, superclass abstrak.


Superkelas abstrak dapat mencegah dirinya diturunkan oleh tipe di luar paketnya. Seseorang yang menerima referensi dari tipe superclass seperti itu, yang mempercayai pembuat paket, dapat yakin bahwa objek tersebut akan berperilaku seperti yang diklaim. Jika sebuah paket memiliki banyak kelas yang ingin mengekspos beberapa fungsionalitas umum, tetapi tidak sesuai dengan hierarki yang tepat (misalnya satu mengimplementasikan fungsi X dan Y, satu Y dan Z, dan satu X dan Z) akan sangat membantu jika dapat mengekspos fungsionalitas menggunakan antarmuka sambil tetap menjanjikan bahwa contoh yang dirujuk oleh jenis antarmuka akan "asli".
supercat

0

Metode terlindungi selalu dapat diakses oleh sub-kelas hanya jika subkelas memperluas kelas dasar.

Dalam kasus antarmuka, subkelas tidak pernah memperluas antarmuka. Ini mengimplementasikan antarmuka.

Metode yang dilindungi dapat diakses melalui perluasan dan bukan dengan implement .


apa bedanya kata kunci apa, tidak masalah.
Alex78191

0

Antarmuka dimaksudkan untuk mengekspos metode ke dunia luar . Dengan demikian metode ini bersifat publik. Namun, jika Anda ingin memperkenalkan abstraksi dalam keluarga kelas yang sama, dimungkinkan dengan membuat tingkat abstraksi lain antara antarmuka Anda dan kelas implementasi, yaitu kelas abstrak. Contohnya ditunjukkan di bawah ini.

public interface MyInterface {
    public void publicMethod(); // needs to be public
}

public abstract class MyAbstractClass implements MyInterface {
    @Override
    public void publicMethod() {
        protectedMethod(); // you can call protected method here
        // do other stuff
    }
    protected abstract void protectedMethod(); // can be protected
}

public class MyClass extends MyAbstractClass {
    @Override
    protected void protectedMethod() {
        // implement protected method here, without exposing it as public
    }
}

2
Tetapi metode pribadi yang tidak akan dilihat oleh siapa pun diizinkan di antarmuka.
Alex78191

java memiliki metode default dalam antarmuka, yaitu antarmuka adalah penopang untuk melewati beberapa pewarisan kelas abstrak. Biarkan beberapa warisan kelas abstrak diperbolehkan. Konflik metode default tidak menjadi masalah.
Alex78191

Kamu benar. Pada Java 9, metode privat diperbolehkan dalam antarmuka. Ini tidak bisa abstrak dan mereka diimplementasikan dan digunakan dalam antarmuka, terutama dengan metode default atau statis lainnya (jika mereka sendiri statis).
Stefanos Kargas

1
Jawaban ini mengabaikan pertanyaan yang diajukan: mengapa antarmuka tidak dapat memiliki metode yang dilindungi? Metode yang dilindungi masih akan "mengekspos metode ke dunia luar" , dan klaim bahwa "metode ini bersifat publik" adalah salah. Mereka publik karena bahasanya dirancang seperti itu, tetapi itu bisa saja mengizinkan metode yang dilindungi di antarmuka. OP hanya menanyakan alasannya.
skomisa
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.