Java neden arayüzde özel üyelere izin vermiyor?


Yanıtlar:


87

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.


9
Yuvalama sınıflarını bir arabirime koyabildiğimiz için, arabirime uygulama koyabiliriz. Bunu yapmak çok yanlış ama yapabiliriz.
emory

29
Java 9, arayüzde özel yöntemlere izin verir, Varsayılan yöntemlerin eklenmesinden sonra mantıklıdır, Ref: bugs.openjdk.java.net/browse/JDK-8071453
Hariharan

3
"Bunu yapmak çok yanlıştır" .. her zamanki gibi, bağlama bağlıdır.
JacksOnF1re

5
Göründüğü kadar kötü değil. Bir arabirimdeki özel yöntemlere yalnızca aynı arabirimdeki varsayılan yöntemlerle erişilebilir. Faydalarından biri, varsayılan yöntemlerin uygulanmasını kapsüllemeyi bozmadan anlamlı küçük işlevlere bölmeye yardımcı olmaktır.
Henry Pham

48

Java 9'da, arayüzlerde özel yöntemler mümkündür.

Java 9 özellikleri

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.


10
@SebiSebi, Java'nın canlı bir dil olduğunu fark ettiğiniz an.
Arashsoft

@Arashsoft, OP alanları soruyor.
Pacerier

19

Ö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.


13

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.


Java-9 arayüz özellikleri hakkında yararlı bilgiler.
Ravindra babu

9

Arabirimi uygulayan herhangi bir sınıf tarafından sağlanan bir API'yi açıklamak için bir arabirim kullanılır. Bir arayüzün tanımına göre durumu olmadığından, içinde alan üyelerini bildirmenin bir faydası yoktur.


Java ülkesinde üye bir alan, yöntem, kurucu veya sınıftır.
emory

7

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 ( ) ; }
}

6

Göre Javaprogramlama dili kapsamı private memberssınırlıdır classo bildirilmiş ve sadece o yöntemleriyle erişilebilir olduğu class. Ancak intefacebir yöntem gövdesi yoktur, bu nedenle özel üyeleri bir interface.


4

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
   }
}

3

Çü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.


Buna katılmıyorum, "Özel bir yöntemi çağırmanın bir yolu yoktur." İç sınıflarda bir yol olacaktır - stackoverflow.com/a/10169894/348975
emory

Java 8'in varsayılan yöntemlerini düşünün. Arayüz I, birçok ortak kod içeren varsayılan A ve B yöntemlerine sahiptir. Bunu yeniden düzenlemek için, yalnızca paylaşılan kodu içeren ve A ve B tarafından çağrılan C yöntemini istersiniz. Java 8'de bu, tüm arabirim uygulamalarına maruz kalan varsayılan bir yöntem olacaktır. Java 9 C'de yalnızca I içindeki varsayılan yöntemlerle görülebilen özel bir yöntem olabilir.
Ivan Krylov

2

ö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.


Burada mezar kazdığım için özür dilerim :( docs.oracle.com/javase/7/docs/api/java/io/Serializable.html bu durumda nasıl çalışır? İnsanlar bunu uygulayıp ardından readObject ve writeObject yöntemlerinin üzerine yazamazlar Bir şey kaçırdığıma eminim
PatrickWalker

1

Özel üyeler arayüzde anlam ifade etmiyor. Arayüz, bir sınıfa, o sınıfın içini görmenize gerek olmayan, tanımlanmış yöntemlerle erişmenin bir yoludur.

Özel üyeler buna katılmıyor.


0

Ö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?


0

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.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.