Saya memiliki dua paket dalam proyek saya: odp.proj
dan odp.proj.test
. Ada beberapa metode yang saya ingin terlihat hanya oleh kelas-kelas dalam dua paket ini. Bagaimana saya bisa melakukan ini?
EDIT: Jika tidak ada konsep subpackage di Jawa, apakah ada cara lain? Saya memiliki metode tertentu yang saya inginkan hanya tersedia untuk penguji dan anggota lain dari paket itu. Haruskah saya membuang semuanya ke dalam paket yang sama? Gunakan refleksi yang luas?
java
package
visibility
encapsulation
Nick Heiner
sumber
sumber
Jawaban:
Kamu tidak bisa Di Jawa tidak ada konsep subpackage, jadi
odp.proj
danodp.proj.test
benar-benar paket yang terpisah.sumber
Nama-nama paket Anda mengisyaratkan bahwa aplikasi di sini adalah untuk pengujian unit. Pola khas yang digunakan adalah untuk meletakkan kelas yang ingin Anda uji dan kode uji unit dalam paket yang sama (dalam kasus Anda
odp.proj
) tetapi dalam pohon sumber yang berbeda. Jadi, Anda akan memasukkan kelassrc/odp/proj
Anda dan kode tes Andatest/odp/proj
.Java memang memiliki pengubah akses "paket" yang merupakan pengubah akses default ketika tidak ada yang ditentukan (mis. Anda tidak menentukan publik, pribadi atau dilindungi). Dengan pengubah akses "paket", hanya kelas di yang
odp.proj
akan memiliki akses ke metode. Tetapi perlu diingat bahwa di Jawa, pengubah akses tidak dapat diandalkan untuk menegakkan aturan akses karena dengan refleksi, akses apa pun dimungkinkan. Pengubah akses hanya bersifat sugestif (kecuali jika ada manajer keamanan yang membatasi).sumber
Ini bukan hubungan khusus antara
odp.proj
danodp.proj.test
- mereka kebetulan dinamai terkait.Jika paket odp.proj.test hanya menyediakan tes maka Anda dapat menggunakan nama paket yang sama (
odp.proj
). IDE seperti Eclipse dan Netbeans akan membuat folder terpisah (src/main/java/odp/proj
dansrc/test/java/odp/proj
) dengan nama paket yang sama tetapi dengan semantik JUnit.Perhatikan bahwa IDE ini akan menghasilkan pengujian untuk metode di
odp.proj
dan membuat folder yang sesuai untuk metode pengujian yang tidak ada.sumber
Ketika saya melakukan ini di IntelliJ, pohon sumber saya terlihat seperti ini:
sumber
Mungkin sedikit tergantung pada motif Anda untuk tidak menampilkannya tetapi jika satu-satunya alasan adalah Anda tidak ingin mencemari antarmuka publik dengan hal-hal yang hanya dimaksudkan untuk pengujian (atau beberapa hal internal lainnya) saya akan meletakkan metode dalam pisahkan antarmuka publik dan minta konsumen metode "tersembunyi" menggunakan antarmuka itu. Itu tidak akan menghentikan orang lain menggunakan antarmuka tetapi saya tidak melihat alasan mengapa Anda harus.
Untuk pengujian unit, dan jika memungkinkan tanpa menulis ulang lot, ikuti saran untuk menggunakan paket yang sama.
sumber
Seperti yang telah dijelaskan orang lain, tidak ada yang namanya "subpackage" di Jawa: semua paket terisolasi dan tidak mewarisi apa pun dari orang tua mereka.
Cara mudah untuk mengakses anggota kelas yang dilindungi dari paket lain adalah dengan memperluas kelas dan menimpa anggota.
Misalnya, untuk mengakses
ClassInA
dalam paketa.b
:buat kelas dalam paket itu yang menimpa metode yang Anda butuhkan di
ClassInA
:Itu memungkinkan Anda menggunakan kelas utama menggantikan kelas di paket lain:
Perhatikan bahwa ini hanya berfungsi untuk anggota yang dilindungi, yang terlihat oleh kelas yang diperluas (warisan), dan bukan anggota paket-pribadi yang hanya terlihat oleh sub / kelas yang diperluas dalam paket yang sama. Semoga ini bisa membantu seseorang!
sumber
Sebagian besar jawaban di sini menyatakan bahwa tidak ada subpackage di Jawa, tetapi itu tidak sepenuhnya akurat. Istilah ini telah dalam Spesifikasi Bahasa Jawa sejauh Jawa 6, dan mungkin lebih jauh ke belakang (sepertinya tidak ada versi JLS yang dapat diakses secara bebas untuk versi Java yang lebih lama). Bahasa di sekitar subpackages tidak banyak berubah di JLS sejak Java 6.
Java 13 JLS :
Konsep subpackage relevan, seperti memberlakukan batasan penamaan antara paket dan kelas / interface:
Namun, batasan penamaan ini adalah satu - satunya signifikansi yang diberikan kepada sub paket oleh bahasa:
Dengan konteks ini, kita dapat menjawab pertanyaan itu sendiri. Karena secara eksplisit tidak ada hubungan akses khusus antara paket dan subpackage-nya, atau antara dua subpackages yang berbeda dari paket induk, tidak ada cara dalam bahasa untuk membuat metode terlihat oleh dua paket berbeda dengan cara yang diminta. Ini adalah keputusan desain yang terdokumentasi dan disengaja.
Entah metode tersebut dapat dibuat publik dan semua paket (termasuk
odp.proj
danodp.proj.test
) akan dapat mengakses metode yang diberikan, atau metode tersebut dapat dibuat paket pribadi (visibilitas default), dan semua kode yang perlu mengaksesnya secara langsung harus dimasukkan ke dalam paket (sub) yang sama dengan metode.Yang mengatakan, praktik yang sangat standar di Jawa adalah memasukkan kode tes dalam paket yang sama dengan kode sumber, tetapi di lokasi yang berbeda pada sistem file. Misalnya, dalam alat pembuatan Maven , konvensi adalah untuk menempatkan file sumber dan uji masing-masing dalam
src/main/java/odp/proj
dansrc/test/java/odp/proj
. Ketika alat build mengkompilasi ini, kedua set file berakhir diodp.proj
paket, tetapi hanyasrc
file yang termasuk dalam artefak produksi; file uji hanya digunakan pada waktu build untuk memverifikasi file produksi. Dengan pengaturan ini, kode pengujian dapat dengan bebas mengakses setiap paket kode pribadi atau dilindungi dari kode yang diuji, karena mereka akan berada dalam paket yang sama.Dalam kasus di mana Anda ingin berbagi kode lintas sub paket atau paket saudara bukan kasus uji / produksi, salah satu solusi yang saya lihat beberapa perpustakaan gunakan adalah dengan meletakkan kode bersama sebagai publik, tetapi mendokumentasikan bahwa itu dimaksudkan untuk perpustakaan internal gunakan saja.
sumber
Tanpa meletakkan pengubah akses di depan metode yang Anda katakan itu adalah paket pribadi.
Lihatlah contoh berikut.
sumber
Dengan kelas PackageVisibleHelper, dan merahasiakannya sebelum PackageVisibleHelperFactory beku, kita dapat memanggil metode launchA (by PackageVisibleHelper) di mana saja :)
sumber