Warum erlaubt Java keine privaten Mitglieder in der Schnittstelle?

Antworten:

85

Aus der Java-Sprachspezifikation (Zugriffssteuerung) :

"Die Java-Programmiersprache bietet Mechanismen für die Zugriffskontrolle, um zu verhindern, dass die Benutzer eines Pakets oder einer Klasse von unnötigen Details der Implementierung dieses Pakets oder dieser Klasse abhängen."

Bei der Zugriffskontrolle geht es darum, Implementierungsdetails auszublenden. Eine Schnittstelle muss nicht ausgeblendet werden.

Matten
quelle
9
Da wir Nestklassen in eine Schnittstelle einfügen können, können wir die Implementierung in die Schnittstelle einfügen. Das ist sehr falsch, aber wir können.
Emory
28
Java 9 erlaubt private Methoden in der Schnittstelle. Es ist logisch nach dem Hinzufügen von Standardmethoden, Ref: bugs.openjdk.java.net/browse/JDK-8071453
Hariharan
3
"Das ist sehr falsch" .. wie immer, hängt vom Kontext ab.
JacksOnF1re
5
Es ist nicht so schlimm, wie es sich anhört. Auf die privaten Methoden in einer Schnittstelle kann nur mit Standardmethoden in derselben Schnittstelle zugegriffen werden. Einer der Vorteile besteht darin, die Implementierung von Standardmethoden in sinnvolle kleinere Funktionen zu unterteilen, ohne die Kapselung zu unterbrechen.
Henry Pham
48

In Java 9 sind private Methoden in Schnittstellen möglich.

Java 9-Spezifikationen

Das javac-Compilerteam freut sich, die Verfügbarkeit von Compiler-Unterstützung für private Methoden in Schnittstellen bekannt zu geben, die mit 9 b54 JDK beginnen.

chiperortiz
quelle
10
@SebiSebi, Der Moment, in dem Sie erkennen, dass Java eine Live-Sprache ist.
Arashsoft
@Arashsoft, OP fragt nach Feldern.
Pacerier
19

Private Schnittstellenmethoden sind Teil von Java 9 als Teil von JEP-213 . Da Schnittstellen in Java 8 Standardmethoden haben können , ermöglichen private Methoden, dass mehrere Standardmethoden eine gemeinsam genutzte private Methode verwenden.

mkobit
quelle
13

Ab Java 8 können Schnittstellen Standardmethoden haben, und ab Java 9 darf eine Schnittstelle über private Methoden verfügen, auf die nur mit Standardmethoden in derselben Schnittstelle zugegriffen werden kann.

Peter Lawrey
quelle
Gut zu wissen über die Funktionen der Java-9-Benutzeroberfläche.
Ravindra Babu
9

Eine Schnittstelle wird zum Beschreiben einer API verwendet, die von einer Klasse bereitgestellt wird, die die Schnittstelle implementiert. Da eine Schnittstelle aus ihrer Definition keinen Status hat, können darin keine Feldmitglieder deklariert werden.

giorashc
quelle
In Java Land ist ein Mitglied ein Feld, eine Methode, ein Konstruktor oder eine Klasse.
Emory
7

Es gäbe keine Möglichkeit, eine solche Schnittstelle zu implementieren. Eine Antwort auf eine von mir gestellte Frage deutet stark darauf hin, dass es unmöglich wäre (ohne radikale Änderung der Regeln), eine Schnittstelle mit privaten Methoden zu implementieren - dies lässt die Frage offen, warum geschützte und paketprivate Methoden nicht zulässig sind.

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

Der folgende Code sollte das gewünschte Ergebnis erzielen. Obwohl alle Methoden öffentlich sind, ist nur die öffentliche Methode effektiv öffentlich. geschützte Methode ist effektiv geschützt. packagePrivateMethod ist effektiv packagePrivate. privateMethod ist effektiv privat.

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

Entsprechend der JavaProgrammiersprache ist der Geltungsbereich des private membersauf das classdeklariert, in dem er deklariert ist, und kann nur mit dessen Methoden aufgerufen werden class. Es intefacegibt jedoch keinen Methodenkörper, daher ist es nicht sinnvoll, private Mitglieder innerhalb eines zu deklarieren interface.

Nishant
quelle
4

Java erlaubt private Methoden in einer Schnittstelle in Java 9 . Die Standardmethoden wurden in Java 8 eingeführt. Es ist möglich, dass mehrere Standardmethoden Code gemeinsam nutzen möchten. Dieser Code kann dann in eine private Methode verschoben werden, ohne ihn der Außenwelt auszusetzen. Dieser Fehler wurde behoben und ab JDK 9 Build 54 wurde die Compilerunterstützung für private Schnittstellenmethoden wiederbelebt.

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
   }
}
akhil_mittal
quelle
3

Es ist, weil sie nutzlos wären.

Es gibt keine Möglichkeit, eine private Methode aufzurufen.

Private Mitglieder sind ein Implementierungsdetail. Bei einer Schnittstelle geht es um die öffentliche Rolle, die eine Klasse übernehmen kann.

WW.
quelle
Ich bin nicht einverstanden mit "Es gibt keine Möglichkeit, eine private Methode aufzurufen." Mit den inneren Klassen würde es einen Weg geben - stackoverflow.com/a/10169894/348975
emory
Betrachten Sie die Standardmethoden von Java 8. Schnittstelle I verfügt über Standardmethoden A und B mit viel allgemeinem Code. Um dies umzugestalten, möchten Sie Methode C, die nur den gemeinsam genutzten Code enthält und von A und B aufgerufen wird. In Java 8 ist dies eine Standardmethode, die allen Schnittstellenimplementierern zur Verfügung steht. in Java 9 C könnte eine private Methode sein, die nur für Standardmethoden innerhalb von I sichtbar ist.
Ivan Krylov
2

Private Felder wären nicht völlig nutzlos, da andere Felder und innere Klassen darauf zugreifen könnten.

Private Methoden konnten jedoch selbst in verschachtelten Klassen nicht implementiert werden, was sie fast unbrauchbar machte. Sie könnten sie mit Reflexion lesen, aber das ist eher ein Randfall.

Peter Lawrey
quelle
Entschuldigung für das Graben hier :( Wie funktioniert docs.oracle.com/javase/7/docs/api/java/io/Serializable.html in diesem Fall? Können die Leute es nicht implementieren und dann die Methoden readObject und writeObject überschreiben Ich bin sicher, ich vermisse etwas
PatrickWalker
1

Private Mitglieder machen in der Benutzeroberfläche keinen Sinn. Die Schnittstelle ist eine Möglichkeit, mit definierten Methoden auf eine Klasse zuzugreifen, bei der Sie die Innereien dieser Klasse nicht sehen müssen.

Private Mitglieder sind damit nicht einverstanden.

Jürgen d
quelle
0

Mitglieder einer Klasse, die als privat deklariert sind, werden nicht von Unterklassen dieser Klasse geerbt. Nur Mitglieder einer Klasse, die als geschützt oder öffentlich deklariert sind, werden von Unterklassen geerbt, die in einem anderen Paket als dem deklariert sind, in dem die Klasse deklariert ist.

Quelle

Sie haben also keine Arbeitsmethoden in einer Schnittstelle, die mit diesem privaten, nicht vererbbaren Feld arbeiten können. Warum sollte es dann existieren?

Alireza Mohamadi
quelle
0

Ja, das kann ich nicht. Für alle, die kommentieren, warum es nicht sollte:

Stellen Sie sich vor, ich habe Klasse A, die Schnittstelle I verwendet. Klasse B erweitert Klasse A und erbt daher auch alle Schnittstellenmethoden in A.

Stellen Sie sich nun vor, ich möchte eine private Methode in Klasse A, möchte sie aber auch für andere Klassen vertraglich definieren (möglicherweise eine Klasse C, die Klasse B oder A nicht unbedingt erweitert).

Vielleicht für eine "Initialisierungs" -Methode, die ich für alle Klassen mit einer I-Schnittstelle möchte. Aber natürlich möchte ich nicht, dass eine Initialisierungsmethode öffentlich ist ... da sie nur einmal verwendet werden sollte oder wie es die Klasse für notwendig hält, nicht nur, weil Sie alles wohl oder übel verwenden möchten.

Die einzige Lösung ist eine Problemumgehung oder das einfache Erzwingen der init-Methode in die Klassen selbst ohne Schnittstelle.

Ich verstehe den Grund sicher nicht so gut, aber dennoch kann es manchmal nützlich sein. Oracle stimmt dem eindeutig zu, da sie private Schnittstellenmethoden in JDK 9 zulassen.

Was ich sowieso getan habe, war eine einfache boolesche Variable zu platzieren, so dass die Schnittstellenmethode (die privat sein sollte) nach einmaligem Setzen als wahr (initialisiert = wahr) gekennzeichnet werden kann. Wenn die Methode dann erneut aufgerufen wird, führt sie einfach nichts aus. Auf diese Weise kann die Schnittstellenmethode als öffentlich implementiert werden. Da jedoch der Konstruktor (meiner Klasse) die Methode zuerst aufruft, wird die Variable auf true gesetzt und kann daher nicht erneut aufgerufen werden.

Andernfalls müssten Sie eine andere Problemumgehung ausprobieren, wenn Sie nur möchten, dass das Innenleben der Klasse sie verwendet. Möglicherweise setzt eine Methode selbst ein Flag ein und aus, wenn sie es verwendet. Wenn das Flag falsch ist, führt die Methode nichts aus (dies ist der Fall, wenn jemand es von außerhalb der Klasse aufruft). Wenn die Klassen eigenen Methoden es aufrufen, setzen sie das Flag schnell auf true, rufen dann die Methode auf und setzen das Flag auf false?

Am Ende irgendwie stumm. Wahrscheinlich ist es vorerst einfach besser, die private Klasse einfach in die Klasse selbst zu platzieren und die Schnittstelle insgesamt auszuschneiden.

Tyrael Erzengel
quelle