Java neden arayüzde özel üyelere izin vermiyor? Belirli bir nedeni var mı?
Java neden arayüzde özel üyelere izin vermiyor? Belirli bir nedeni var mı?
Yanıtlar:
Gönderen Java Dil Spec, (Erişim Kontrol) :
"Java programlama dili, bir paket veya sınıfın kullanıcılarının o paket veya sınıfın uygulanmasının gereksiz ayrıntılarına bağlı kalmasını önlemek için erişim kontrolü mekanizmaları sağlar."
Erişim kontrolü, uygulama ayrıntılarını gizlemekle ilgilidir. Bir arayüzün gizlenecek bir uygulaması yoktur.
Java 9'da, arayüzlerde özel yöntemler mümkündür.
Javac derleyici ekibi, JDK'nın 9 b54 derlemesiyle başlayan arabirimlerde özel yöntemler için derleyici desteğinin mevcut olduğunu duyurmaktan memnuniyet duyar.
Özel arayüz yöntemleri, JEP-213'ün bir parçası olarak Java 9'un bir parçasıdır . Java 8'deki arayüzler varsayılan yöntemlere sahip olabileceğinden , özel yöntemler birden çok varsayılan yöntemin paylaşılan bir özel yöntemi kullanmasına izin verir.
Java 8'den itibaren, arayüzler varsayılan yöntemlere sahip olabilir ve Java 9'dan itibaren, bir arabirimin yalnızca aynı arabirimde varsayılan yöntemlerle erişilebilen özel yöntemlere sahip olmasına izin verilir.
Böyle bir arayüz gerçekleştirmenin hiçbir yolu olmayacaktı. Kuvvetle sorduğum bir sorunun cevabı , özel yöntemlerle bir arayüz uygulamanın (kuralları kökten değiştirmeden) imkansız olacağını gösteriyor - bu, korumalı ve paket özel yöntemlere neden izin verilmediği sorusunu açık bırakıyor.
class OuterClass
{
void run ( MyInterface x )
{
x . publicMethod ( ) ; // why not?
x . protectedMethod ( ) ; // why not?
x . packagePrivateMethod ( ) ; // why not?
x . privateMethod ( ) ; // why not?
}
interface MyInterface
{
public abstract void publicMethod ( ) ; // OK
protected abstract void protectedMethod ( ) ; // why not?
abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private
private void privateMethod ( ) ; // impossible to implement
}
class MyImpl implements MyInterface
{
public void publicMethod ( ) { } // ok
protected void protectedMethod ( ) { } // no sweat
void packagePrivateMethod ( ) { } // no sweat
private void privateMethod ( ) { } // not happening
}
}
Aşağıdaki kod istenen sonucu elde etmelidir. Tüm yöntemler halka açık olsa da, yalnızca genel yöntem etkin bir şekilde halka açıktır. korunan yöntem etkin bir şekilde korunur. packagePrivateMethod etkin bir şekilde packagePrivate'dir. privateMethod etkili bir şekilde özeldir.
class WorkAround
{
void run ( MyPrivateInterface x )
{
x . publicMethod ( ) ;
x . protectedMethod ( ) ;
x . packagePrivateMethod ( ) ;
x . privateMethod ( ) ;
}
public interface MyPublicInterface { void publicMethod ( ) ; }
protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }
interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }
private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}
Java, Java 9'da bir arayüzde özel yöntemlere izin verir . Varsayılan yöntemleri Java 8. Birden varsayılan yöntemleri bazı kodlar paylaşmak istiyorum mümkündür tanıtıldı, daha sonra bu kod dış dünyaya maruz kalmadan özel yönteme hareket ettirilebilir. Bu hata düzeltildi ve JDK 9 build 54'ten başlayarak, özel arayüz yöntemleri için derleyici desteği yeniden canlandırıldı.
public interface IData{
default void processData(int data) {
validate(data);
// do some work with it
}
default void consumeData(int data) {
validate(data);
// do some work with it
}
private void validate(int data) {
// validate data
}
}
Çünkü işe yaramazlar.
Özel bir yöntemi çağırmanın bir yolu yoktur.
Özel üyeler bir uygulama detayıdır. Arayüz, bir sınıfın üstlenebileceği genel rolle ilgilidir.
özel alanlar, diğer alanlar ve iç sınıflar bunlara erişebildiği için tamamen yararsız olmayacaktır.
Ancak özel yöntemler, iç içe geçmiş sınıflarda bile uygulanamadı ve bu da onları neredeyse işe yaramaz hale getirdi. Bunları yansıma kullanarak okuyabilirsiniz, ancak bu daha çok uç bir durumdur.
Özel olarak bildirilen bir sınıfın üyeleri, o sınıfın alt sınıfları tarafından miras alınmaz. Yalnızca korumalı veya genel olarak bildirilen bir sınıfın üyeleri, sınıfın bildirildiği paket dışındaki bir pakette bildirilen alt sınıflar tarafından miras alınır.
Kaynak
Yani bir arayüzde, miras alınamayan özel alanla çalışabilecek herhangi bir çalışma yönteminiz yok, O halde neden var olsun?
Evet, bunu yapamazsın. Neden olmaması gerektiği konusunda yorum yapan herkes için:
Arabirim I'i kullanan Sınıf A'ya sahip olduğumu hayal edin. Sınıf B, Sınıf A'yı genişletiyor, bu nedenle A'daki tüm arabirim yöntemlerini de miras alıyor.
Şimdi, Sınıf A'da özel bir yöntem istediğimi, ancak diğer sınıflar için de sözleşmeye dayalı olarak tanımlanmasını istediğimi hayal edin (Belki de Sınıf B veya A'yı genişletmeyen bir C sınıfı).
Belki bir I arabirimi kullanan tüm sınıflar için istediğim bir "başlatma" yöntemi için. Ama açıkçası, bir başlatma yönteminin herkese açık olmasını istemiyorum .... çünkü sadece bir kez kullanılmalı ya da sınıfın gerekli gördüğü şekilde, sadece hepsini isteyerek kullanmak istemediğin için değil.
Tek çözüm bir geçici çözüm veya init yöntemini bir arabirim olmadan sınıfların kendisine zorlayarak.
Sebebini de anlıyorum, elbette, ama yine de bazen işe yarayabilir. Açıkça Oracle, JDK 9'da özel arayüz yöntemlerine izin verdiklerini kabul ediyor.
Yine de benim için yaptığım şey basit bir boole değişkeni yerleştirmekti, bu şekilde arayüz yöntemi (özel olmalıdır) bir kez ayarlandıktan sonra doğru (başlatıldı = doğru) olarak işaretlenebilir. Sonra tekrar çağrıldığında, yöntem hiçbir şey yapmaz. Bu şekilde arabirim yöntemi genel olarak uygulanabilir, ancak (benim sınıfımın) oluşturucusu yöntemi ilk olarak çağırdığından, bu, değişkeni true olarak ayarlar ve böylece tekrar çağrılamaz.
Aksi takdirde, yalnızca sınıfın iç işleyişlerinin onu kullanmasını istiyorsanız, farklı bir geçici çözüm denemeniz gerekir ... Belki de bir yöntemin kendisi, onu kullanırken bir bayrak açar ve kapatır. Bayrak yanlış olduğunda, yöntem hiçbir şey yapmaz (bu, birisi onu sınıfın dışından çağırdığında olur). Ancak, sınıfların kendi yöntemleri onu çağırdığında, bayrağı hızlı bir şekilde true olarak ayarlarlar, ardından yöntemi çağırırlar, ardından bayrağı false olarak ayarlarlar ??
Sonunda bir çeşit sessizlik. Muhtemelen şimdilik özel sınıfı sınıfın içine yerleştirmek ve arayüzü tamamen kesmek daha iyidir.