Jawaban:
Menempatkan anggota statis ke dalam sebuah antarmuka (dan mengimplementasikan antarmuka itu) adalah praktik yang buruk dan bahkan ada nama untuk itu, Antipattern Antarmuka Konstan , lihat Java Efektif , Item 17:
Pola antarmuka yang konstan adalah penggunaan antarmuka yang buruk . Bahwa kelas menggunakan beberapa konstanta secara internal adalah detail implementasi. Mengimplementasikan antarmuka yang konstan menyebabkan detail implementasi ini bocor ke API yang diekspor kelas. Ini bukan konsekuensi bagi pengguna kelas yang mengimplementasikan antarmuka konstan. Bahkan, hal itu mungkin membingungkan mereka. Lebih buruk lagi, ini merepresentasikan sebuah komitmen: jika dalam rilis mendatang kelas tersebut dimodifikasi sehingga tidak lagi perlu menggunakan konstanta, ia masih harus mengimplementasikan antarmuka untuk memastikan kompatibilitas biner. Jika kelas nonfinal mengimplementasikan antarmuka konstan, semua subkelasnya akan memiliki ruang nama yang tercemar oleh konstanta di antarmuka.
Ada beberapa antarmuka konstan di pustaka platform java, seperti
java.io.ObjectStreamConstants
. Antarmuka ini harus dianggap sebagai anomali dan tidak boleh ditiru.
Untuk menghindari beberapa jebakan antarmuka konstan (karena Anda tidak dapat mencegah orang mengimplementasikannya), kelas yang tepat dengan konstruktor pribadi harus lebih disukai (contoh dipinjam dari Wikipedia ):
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
Dan untuk mengakses konstanta tanpa harus sepenuhnya mengkualifikasinya (yaitu tanpa harus mengawalnya dengan nama kelas), gunakan impor statis (karena Java 5):
import static Constants.PLANCK_CONSTANT;
import static Constants.PI;
public class Calculations {
public double getReducedPlanckConstant() {
return PLANCK_CONSTANT / (2 * PI);
}
}
" Pola antarmuka yang konstan adalah penggunaan antarmuka yang buruk "
Siapa pun yang mengarang hipotesis ini, betapapun dia menjadi guru, mengarangnya atas dasar kebutuhan untuk terus menerapkan kebiasaan dan praktik buruk secara efisien. Hipotesis ini didasarkan pada promosi validitas kebiasaan desain perangkat lunak yang buruk.
Saya menulis bantahan tanggapan terhadap hipotesis itu di sini: Apa cara terbaik untuk mengimplementasikan konstanta di Java? menjelaskan dasar-dasar hipotesis ini.
Selama 10 tahun pertanyaan itu tetap terbuka, sampai ditutup dalam waktu 2 jam setelah saya memposting alasan saya yang tidak membenarkan hipotesis ini, sehingga menyingkapkan KETIDAKAAN untuk diperdebatkan oleh mereka yang memegang teguh hipotesis yang salah arah ini.
Ini adalah poin-poin yang saya ungkapkan melawan hipotesis
Dasar untuk memegang hipotesis ini adalah perlunya metode dan aturan PEMBATASAN untuk mengatasi efek dari kebiasaan dan metodologi perangkat lunak yang buruk.
Para pendukung sentimen " Pola antarmuka konstan adalah penggunaan antarmuka yang buruk" tidak dapat memberikan alasan apa pun selain yang disebabkan oleh kebutuhan untuk mengatasi efek dari kebiasaan dan praktik buruk tersebut.
Pecahkan masalah fundamental.
Dan kemudian mengapa tidak memanfaatkan sepenuhnya dan memanfaatkan setiap fitur bahasa dari struktur bahasa Java untuk kenyamanan Anda sendiri. Tidak Perlu Jaket. Mengapa menciptakan aturan untuk menghalangi gaya hidup Anda yang tidak efektif untuk mendiskriminasi dan memberatkan gaya hidup yang lebih efektif?
adalah organisasi informasi. Informasi memediasi proses, dan perilaku informasi itu pertama-tama harus dipahami, bersama dengan apa yang disebut aturan bisnis - sebelum merekayasa atau melengkapi solusi untuk proses tersebut. Metode organisasi informasi seperti itu disebut normalisasi data beberapa dekade yang lalu.
Kemudian hanya rekayasa solusi yang dimungkinkan karena menyelaraskan granularitas dan modularitas komponen solusi dengan granularitas dan modularitas komponen informasi adalah strategi optimal.
Ada dua atau tiga hambatan yang signifikan dalam mengatur informasi.
Minimnya persepsi akan kebutuhan "normalisasi" model data.
Pernyataan EF Codd tentang normalisasi data cacat, cacat dan ambigu.
Tren terbaru yang menyamar sebagai agile engineering adalah anggapan yang salah bahwa seseorang tidak boleh merencanakan dan mengkondisikan organisasi modul ke depan karena Anda dapat melakukan refactor saat Anda melanjutkan. Refactoring dan perubahan terus menerus tanpa terhalang oleh penemuan-penemuan di masa depan digunakan sebagai alasan. Penemuan esensial dari perilaku informasi proses kemudian, dengan menggunakan trik akuntansi untuk menunda keuntungan dan asetisasi, oleh karena itu pengetahuan esensial dan perlakuannya dianggap tidak diperlukan sekarang.
Jangan membuat aturan atau mengeluarkan fatwa apa pun yang menentangnya hanya karena Anda menyukai kebiasaan pemrograman tabrak lari ad-hoc.
Jangan melarang kepemilikan senjata dengan alasan ada orang yang entah bagaimana cara memegang senjata atau rawan menyalahgunakan senjata.
Jika aturan yang Anda buat dimaksudkan untuk pemula pemrograman yang tidak dapat membuat kode secara profesional dan Anda menghitung sendiri di antara mereka, maka katakan demikian - jangan nyatakan fatwa Anda sebagaimana berlaku untuk model data yang dinormalisasi dengan benar.
Saya tidak peduli apa niat asli dari para pendiri negara untuk Konstitusi AS. Saya tidak peduli dengan niat tidak diubah yang tidak tertulis. Saya hanya peduli tentang apa yang secara literal dikodifikasi dalam Konstitusi tertulis dan bagaimana saya dapat memanfaatkannya untuk fungsi masyarakat yang efektif.
Saya hanya peduli tentang apa yang diizinkan oleh spesifikasi bahasa / platform Java dan saya berniat untuk mengeksploitasinya secara maksimal untuk memberi saya media untuk mengekspresikan solusi perangkat lunak saya secara efisien dan efektif. Tidak perlu jaket.
Ini membutuhkan penulisan kode tambahan untuk memetakan parameter ke nilai. Fakta bahwa pendiri Java tidak menyediakan pemetaan nilai parameter tanpa Anda menulis bahwa kode pemetaan mendemonstrasikan Konstanta Enum sama seperti penggunaan bahasa Java yang tidak diinginkan.
Terutama karena Anda tidak dianjurkan untuk menormalkan dan mengkomponen parameter Anda, akan ada kesan palsu bahwa parameter yang dicampur ke dalam kantong Enum memiliki dimensi yang sama.
Jangan lupakan itu. Jika Anda mendesain dan menormalkan model data Anda, dan mereka menyertakan konstanta, maka konstanta tersebut adalah kontrak. Jika Anda tidak menormalkan model data Anda, maka Anda harus menyesuaikan diri dengan fatwa yang diberikan tentang cara mempraktikkan pengkodean terbatas untuk mengatasi kebiasaan buruk itu.
Oleh karena itu, Antarmuka adalah cara sempurna untuk mengimplementasikan kontrak Konstanta.
Ya. Siapa pun dapat secara tidak sengaja menerapkan antarmuka apa pun secara tidak sengaja. Tidak ada yang akan menghalangi pemrogram yang tidak sengaja seperti itu.
Jangan menempatkan keputusan yang membatasi untuk melindungi dugaan praktik buruk yang menyebabkan bocornya parameter yang tidak dikontrak / menyimpang ke dalam API. Selesaikan masalah fundamental, daripada menyalahkan Konstanta Antarmuka.
Seorang programmer yang berfungsi normal dan EFEKTIF tidak ada di sana untuk membuktikan berapa lama dia bisa bertahan di bawah air, seberapa jauh dia bisa berjalan dalam panas terik atau hujan badai. Dia harus menggunakan alat yang efisien seperti mobil atau bus atau setidaknya sepeda untuk menempuh jarak 10 mil ke tempat kerja setiap hari.
Jangan membatasi sesama programmer hanya karena Anda memiliki obsesi esoteris asketisme dengan pemrograman tanpa IDE.
OSGI adalah kerangka kerja seperti itu. Dan begitu juga keputusan terhadap Konstanta Antarmuka.
Konstanta antarmuka adalah cara yang efektif dan efisien untuk ditempatkan ke dalam komponen model data yang dirancang dan dinormalisasi dengan baik.
Konstanta antarmuka dalam antarmuka pribadi yang diberi nama dengan tepat yang disarangkan di file kelas juga merupakan praktik yang baik untuk mengelompokkan semua konstanta pribadi Anda daripada menyebarkannya ke seluruh file.
Saya menemukan pertanyaan lama ini beberapa kali sekarang dan jawaban yang diterima masih membingungkan saya. Setelah banyak berpikir, saya rasa pertanyaan ini bisa lebih diperjelas.
Bandingkan saja:
public final class Constants {
private Constants() {
// restrict instantiation
}
public static final double PI = 3.14159;
public static final double PLANCK_CONSTANT = 6.62606896e-34;
}
vs.
public interface Constants {
double PI = 3.14159;
double PLANCK_CONSTANT = 6.62606896e-34;
}
Penggunaan yang sama. Apalagi kode.
Saya pikir jawaban @Pascal Thivent memiliki penekanan yang salah, ini versi saya:
Menempatkan anggota statis ke dalam sebuah antarmuka ( dan mengimplementasikan antarmuka itu ) adalah praktik yang buruk.
Kutipan dari Java Efektif memiliki asumsi antarmuka konstan yang diterapkan oleh orang lain, yang menurut saya tidak boleh (dan tidak akan) terjadi.
Saat Anda membuat antarmuka konstan dengan nama seperti Constants
itu, ini tidak boleh diterapkan oleh siapa pun. (meskipun secara teknis mungkin, yang merupakan satu-satunya masalah di sini)
Pustaka standar tidak dapat menanggung kemungkinan penyalahgunaan desain, jadi Anda tidak akan melihatnya di sana.
Namun , untuk proyek-proyek harian pengembang normal, menggunakan konstanta antarmuka adalah jauh lebih mudah karena Anda tidak perlu khawatir tentang static
, final
,empty constructor
, dll, dan itu akan tidak menimbulkan masalah desain yang buruk. Satu-satunya downside yang dapat saya pikirkan adalah masih memiliki nama "antarmuka", tetapi tidak lebih dari itu.
Pada akhirnya, saya pikir semua orang hanya mengutip dari buku, dan memberikan pendapat serta pembenaran atas pendirian mereka. Tidak terkecuali bagi saya. Mungkin keputusan masih tergantung pada pengembang masing-masing proyek. Silakan gunakan jika Anda merasa nyaman. Hal terbaik yang dapat kami lakukan adalah membuatnya konsisten di seluruh proyek .
public
juga dapat dihilangkan karena ini adalah antarmuka, membuatnya hanya double PI = 3.14159;
Penggunaan Constants.PI
tidak memerlukan kelas yang menggunakan ini untuk mengimplementasikan Constants
antarmuka! Saya pikir pendekatan antarmuka jauh lebih bersih dalam hal penggunaan, IMHO
Joshua Bloch, "Java Efektif - Panduan Bahasa Pemrograman":
Pola antarmuka yang konstan adalah penggunaan antarmuka yang buruk. Bahwa kelas menggunakan beberapa konstanta secara internal adalah detail implementasi. Mengimplementasikan antarmuka yang konstan menyebabkan detail implementasi ini bocor ke API yang diekspor kelas. Ini bukan konsekuensi bagi pengguna kelas yang mengimplementasikan antarmuka konstan. Bahkan, hal itu mungkin membingungkan mereka. Lebih buruk lagi, ini mewakili sebuah komitmen: jika di rilis mendatang kelas tersebut dimodifikasi sehingga tidak lagi perlu menggunakan konstanta, ia masih harus mengimplementasikan antarmuka untuk memastikan kompatibilitas biner. Jika kelas nonfinal mengimplementasikan antarmuka konstan, semua subkelasnya akan memiliki namespace yang tercemar oleh konstanta di antarmuka.
Mereka berguna jika Anda memiliki konstanta umum yang akan digunakan di kelas yang mengimplementasikan antarmuka.
Berikut ini contohnya: http://www.javapractices.com/topic/TopicAction.do?Id=32
Namun perlu diperhatikan bahwa praktik yang direkomendasikan adalah menggunakan impor statis, bukan konstanta dalam antarmuka. Berikut referensinya: http://www.javapractices.com/topic/TopicAction.do?Id=195
Ada jawaban yang sangat masuk akal.
Tetapi saya memiliki beberapa pemikiran tentang pertanyaan ini. (mungkin salah)
Menurut pendapat saya, bidang dalam antarmuka, seharusnya tidak menjadi konstanta untuk keseluruhan proyek, mereka hanya sarana untuk antarmuka dan antarmuka memperluasnya dan kelas yang mengimplementasikan antarmuka ini atau memiliki hubungan dekat dengannya. Mereka harus digunakan dalam rentang tertentu bukan global.
Dua poin tentang antarmuka:
Antarmuka mendeskripsikan subset dari objek yang mengimplementasikannya. (Ini adalah intuisi)
Antarmuka mendeskripsikan konstanta umum diikuti oleh objek yang mengimplementasikannya.
Jadi menurut saya jika Constants Interface tidak digunakan untuk konstanta global , maka itu dapat diterima:
implements
itu (dan, tentu saja, gunakan konstanta umum ini dalam implementasi).Contoh:
interface Drawable {
double GOLDEN_RATIO = 1.618033988;
double PI = 3.141592653;
...
// methods
...
}
public class Circle implements Drawable {
...
public double getCircumference() {
return 2 * PI * r;
}
}
void usage() {
Circle circle = new Circle(radius: 3.0);
double maxRadius = 5.0;
if ( circle.getCircumference() < 2 * Circle.PI * maxRadius ) {
...
}
}
Dalam contoh ini:
Circle implements Drawable
, Anda segera tahu bahwa Circle
mungkin sesuai dengan konstanta yang ditentukan Drawable
, jika tidak, mereka harus memilih nama yang lebih buruk karena nama yang baik PI
dan GOLDEN_RATIO
telah diambil!Drawable
benda - benda ini yang sesuai dengan spesifikasi PI
dan GOLDEN_RATIO
definisi Drawable
, mungkin ada benda yang tidak Drawable
memiliki presisi yang berbeda dari rasio pi dan emas.The javax.swing.SwingConstants
antarmuka adalah contoh yang mendapat bidang statis yang digunakan antara kelas ayunan. Ini memungkinkan Anda untuk dengan mudah menggunakan sesuatu seperti
this.add(LINE_START, swingcomponent);
this.add(this.LINE_START, swingcomponent);
atau this.add(SwingComponents.LINE_START, swingcomponent);
Namun antarmuka ini tidak memiliki metode ...
Saya menemukan pertanyaan ini dan berpikir saya akan menambahkan sesuatu yang tidak disebutkan. Secara umum, saya setuju dengan jawaban Pascal di sini . Namun, saya tidak berpikir konstanta pada antarmuka "selalu" antipattern.
Misalnya, jika konstanta yang Anda tentukan adalah bagian dari kontrak untuk antarmuka itu, menurut saya antarmuka adalah tempat yang tepat untuk konstanta. Dalam beberapa kasus, tidak tepat untuk memvalidasi parameter Anda secara pribadi tanpa mengekspos kontrak kepada pengguna implementasi Anda. Tanpa kontrak publik, pengguna hanya dapat menebak dengan apa validasi Anda, singkatnya mendekompilasi kelas dan membaca kode Anda.
Jadi, jika Anda mengimplementasikan sebuah antarmuka dan antarmuka tersebut memiliki konstanta yang Anda gunakan untuk memastikan kontrak Anda (seperti rentang integer misalnya), maka pengguna kelas Anda dapat memastikan bahwa mereka menggunakan instance antarmuka dengan benar dengan memeriksa konstanta di antarmuka diri. Ini tidak mungkin jika konstanta bersifat pribadi untuk implementasi Anda atau implementasi Anda bersifat paket atau semacamnya.
Saya menggunakan konstanta antarmuka saat berhadapan dengan konstanta bersama antar kelas.
public interface TestConstants
{
String RootLevelConstant1 = "RootLevelConstant1";
interface SubGroup1
{
String SubGroupConstant1 = "SubGroup1Constant1";
String SubGroupConstant2 = "SubGroup1Constant2";
}
interface SubGroup2
{
String SubGroupConstant1 = "SubGroup2Constant1";
String SubGroupConstant2 = "SubGroup2Constant2";
}
}
Pengelompokan adalah aset besar, terutama dengan kumpulan konstanta yang besar.
Untuk menggunakannya, Anda cukup menyatukannya:
System.out.println(TestConstants.SubGroup1.SubGroupConstant1);
System.out.println(TestConstants.SubGroup2.SubGroupConstant1);
System.out.println(TestConstants.RootLevelConstant1);