Saya baru saja memperhatikan ada pilihan untuk memiliki metode statis di antarmuka. Sama seperti dengan bidang antarmuka statis, ada perilaku yang menarik: Ini tidak diwariskan.
Saya tidak yakin apakah ini berguna dalam antarmuka aktual yang akan diterapkan. Namun, ini memungkinkan programmer untuk membuat antarmuka yang hanya mencakup hal-hal statis, seperti misalnya kelas utilitas.
Contoh sederhana hanyalah sebuah amplop untuk konstanta global. Dibandingkan dengan kelas, Anda dapat dengan mudah melihat pelat ketel yang hilang public static final
seperti yang diasumsikan (membuatnya kurang bertele-tele).
public interface Constants {
String LOG_MESSAGE_FAILURE = "I took an arrow to the knee.";
int DEFAULT_TIMEOUT_MS = 30;
}
Anda juga bisa membuat sesuatu yang lebih kompleks, seperti pseudo-enum kunci konfigurasi ini.
public interface ConfigKeys {
static createValues(ConfigKey<?>... values) {
return Collections.unmodifiableSet(new HashSet(Arrays.asList(values)));
}
static ConfigKey<T> key(Class<T> clazz) {
return new ConfigKey<>(clazz);
}
class ConfigKey<T> {
private final Class<T> type;
private ConfigKey(Class<T> type) {
this.type = type;
}
private Class<T> getType() {
return type;
}
}
}
import static ConfigKeys.*;
public interface MyAppConfigKeys {
ConfigKey<Boolean> TEST_MODE = key(Boolean.class);
ConfigKey<String> COMPANY_NAME = key(String.class);
Set<ConfigKey<?>> VALUES = createValues(TEST_MODE, COMPANY_VALUE);
static values() {
return VALUES;
}
}
Anda juga dapat membuat beberapa "kelas" utilitas dengan cara ini. Namun, dalam utilitas, seringkali berguna untuk menggunakan metode pembantu pribadi atau terlindungi, yang tidak mungkin dilakukan di kelas.
Saya menganggapnya sebagai fitur baru yang bagus, dan terutama fakta bahwa anggota statis tidak diwarisi adalah konsep yang menarik yang diperkenalkan ke antarmuka saja.
Saya ingin tahu apakah Anda dapat menganggapnya sebagai praktik yang baik. Sementara gaya kode dan praktik terbaik tidak aksiomatis dan ada ruang untuk berpendapat, saya pikir biasanya ada alasan yang sah untuk mendukung pendapat tersebut.
Saya lebih tertarik dengan alasan (tidak) menggunakan pola seperti ini.
Perhatikan bahwa saya tidak bermaksud mengimplementasikan antarmuka tersebut. Mereka hanyalah sebuah amplop untuk konten statis mereka. Saya hanya bermaksud menggunakan konstanta atau metode dan mungkin menggunakan impor statis.
default
metode. Saya berbicara tentangstatic
metode dan bidang. Itu tidak diwariskan, jadi mereka tidak merusak banyak warisan.Jawaban:
Menempatkan konstanta pada antarmuka disebut
Constant Interface Antipattern
konstanta karena seringkali hanya sekedar detail implementasi. Kelemahan lebih lanjut dirangkum dalam artikel Wikipedia pada antarmuka Konstan .Memang dokumen Java menyatakan bahwa metode statis dapat membuatnya lebih mudah untuk mengatur metode helper, misalnya ketika memanggil metode helper dari metode default.
sumber
Seperti yang dinyatakan dalam pertanyaan, antarmuka tidak dimaksudkan untuk diimplementasikan (atau dipakai). Jadi kita bisa membandingkannya dengan kelas yang memiliki konstruktor pribadi:
super()
untuk memanggil, tetapi antarmuka dapat "diimplementasikan"new MyInterface() {};
Perbandingan ini mendukung kelas karena memungkinkan lebih banyak kontrol. Yang mengatakan, kelas tidak dimaksudkan untuk menjadi pemegang barang-barang statis, Anda akan mengharapkannya memiliki instance. Ya, tidak ada pilihan yang sempurna.
Ada juga hal aneh tentang warisan dari "antarmuka statis":
Ini mungkin alasan untuk menganggapnya sebagai pola yang buruk dan tetap menggunakan kelas statis untuk kasus ini. Namun, bagi seseorang yang kecanduan gula sintaksis mungkin masih menggoda bahkan dengan kerugiannya.
sumber
Sebagai @MarkusPscheidt ide ini pada dasarnya adalah perpanjangan dari antipattern Interface Konstan . Pendekatan ini awalnya digunakan secara luas untuk memungkinkan satu set konstanta diwarisi oleh banyak kelas yang berbeda. Alasan mengapa ini dianggap sebagai antipattern adalah karena masalah yang ditemui menggunakan pendekatan ini dalam proyek nyata. Saya tidak melihat alasan untuk berpikir bahwa masalah ini hanya akan berhubungan dengan konstanta.
Mungkin yang lebih penting, benar-benar tidak perlu melakukan ini. Gunakan impor statis sebagai gantinya dan secara eksplisit tentang apa yang Anda impor dan dari mana.
sumber
interface ColorFilter {Image applyGradient(int colorSpace, int width, byte[] pixels); }
. Saya bisa membayangkan ada menjadi beberapa konstanta yang berbedaRGB
,RGBA
,CMYK
,GREYSCALE
,INDEXED
dllSaya akan mengatakan, jika Anda tertarik tentang cara menggunakan fitur baru dengan benar, lihat kode di JDK. Metode default pada antarmuka sangat banyak digunakan dan mudah ditemukan, tetapi metode statis pada antarmuka tampaknya sangat jarang. Beberapa contoh termasuk
java.time.chrono.Chronology
,java.util.Comparator
,java.util.Map
, dan beberapa interface dalamjava.util.function
danjava.util.stream
.Sebagian besar contoh yang saya lihat melibatkan penggunaan API yang cenderung sangat umum: konversi antara berbagai jenis dalam API waktu, misalnya, untuk perbandingan yang cenderung sering dilakukan antara objek yang diteruskan ke fungsi atau objek yang terkandung dalam koleksi. Takeaway saya: jika ada bagian dari API Anda yang harus fleksibel, tetapi Anda dapat menutupi mengatakan 80% kasus penggunaan dengan beberapa standar, pertimbangkan untuk menggunakan metode statis pada antarmuka Anda. Mengingat betapa jarangnya fitur ini tampaknya digunakan di JDK, saya akan sangat konservatif ketika memanfaatkannya dalam kode saya sendiri.
Contoh Anda tidak terlihat seperti apa yang saya lihat di JDK. Untuk kasus-kasus tertentu, Anda hampir pasti akan membuat
enum
yang mengimplementasikan antarmuka yang diinginkan. Antarmuka menggambarkan seperangkat perilaku dan benar-benar tidak memiliki bisnis mempertahankan koleksi implementasinya.sumber
Bagaimana dengan, um, kompatibilitas dengan JVM lama?
Tidak. Ini adalah perubahan yang tidak kompatibel ke belakang yang menambah zilch pada ekspresivitas bahasa. Dua jempol ke bawah.
Saya sangat merekomendasikan menggunakan kelas untuk memuat detail implementasi. Antarmuka benar-benar hanya dimaksudkan untuk mengatakan "Objek ini mendukung operasi XYZ" dan itu tidak ada hubungannya dengan metode statis apa pun yang mungkin Anda pikirkan untuk dimasukkan ke dalam deklarasi antarmuka. Fitur ini seperti kursi malas dengan kulkas mini bawaan. Tentu itu memiliki beberapa kegunaan niche tetapi tidak menarik cukup berat untuk pantas menjadi arus utama.
UPDATE: Harap tidak ada lagi downvotes. Jelas beberapa orang berpikir metode statis di antarmuka adalah lutut lebah, dan saya menyerah. Saya akan segera menghapus jawaban ini tetapi komentar yang terlampir adalah diskusi yang menarik.
sumber