Was ist die Verwendung von weniger restriktiven Mitgliedszugriffsmodifikatoren als der Klassenzugriffsmodifikator?

9

Angenommen, ich habe eine Klasse mit einigen Mitgliedern, und die Mitglieder haben einen weniger restriktiven Zugriffsmodifikator als die Klasse selbst.

Ein konkretes Beispiel könnte sein:

package apples;

class A { // package private
    public int foo() { // public (=> less restrictive than *package private*)
        return 42;
    }
}

Zu meinem Verständnis einer Klasse Zugriffsmodifikator , die restriktiver als das ist Mitglied Zugriffsmodifikator , wird außer Kraft setzen , die weniger restriktive Mitglied Zugriffsmodifikatoren . Ein weniger restriktiver Modifikator für den Mitgliederzugriff sollte daher überhaupt keine Auswirkung haben.

  • Ist mein Verständnis richtig?
    • Wenn nicht, was sind die Konsequenzen?
  • Was könnten triftige Gründe für weniger restriktive Mitgliederzugriffsmodifikatoren sein?
  • Was gibt es schließlich als bewährte Methode?

Ich habe auch experimentiert, weil ich dachte, dass dies Konsequenzen haben könnte, wenn ich anfange, Funktionsreferenzen weiterzugeben, aber selbst dann scheint der Zugriffsmodifikator keine Rolle zu spielen.

Die Situation, die ich konstruiert habe, ist die folgende:

  • apples.Bstellt eine öffentliche Methode bereit bla(), die einen Verweis auf zurückgibt apples.A.foo.
  • Dann pizzas.Cruft apples.B.blaeinen Verweis auf erhalten , A.foound es nennt.
  • Ist A.foo()also nicht direkt sichtbar C, sondern nur indirekt über erreichbarB.bla()

Ich habe es getestet und es macht keinen Unterschied, ob ich den Zugriffsmodifikator des foo() Pakets privat mache oder nicht.

package apples;

import java.util.function.IntSupplier;

public class B {
    public IntSupplier getReferenceToAFoo() {
        A aInstance = new A();
        return aInstance::foo;
    }
}
package pizzas;

import apples.B;

import java.util.function.IntSupplier;

public class C {
    private int callAFooIndirectly() {
        B bInstance = new B();
        IntSupplier intsupplier = bInstance.getReferenceToAFoo();
        return intsupplier.getAsInt();
    }

    public static void main(String[] args) {
        C cInstance = new C();

        int i = cInstance.callAFooIndirectly();
        System.out.println(i);
        assert 42 == i;
    }
}

Stefan D.
quelle
2
Der mit Abstand häufigste Grund für diese Art von Design ist die Bereitstellung von Implementierungen öffentlicher API-Methoden (z. B. von Schnittstellen oder erweiterten abstrakten Klassen) unter Verwendung nicht öffentlicher Klassen. Das JDK selbst ist voll mit solchen Klassen (zB: java.util.Collections.SingletonSet<E>ist privatein java.util.Collections).
ernest_k

Antworten:

8

Ist mein Verständnis richtig?

Ja.

Was könnten triftige Gründe für weniger restriktive Mitgliederzugriffsmodifikatoren sein?

Zwei Gründe:

  • Manchmal implementieren Sie eine Schnittstelle. Schnittstellenmethoden müssen seinpublic
  • Dies erleichtert das Ändern des Gesamtzugriffs Ihrer Klasse. Wenn Sie beispielsweise alle Methoden markieren, die Sie jemals öffentlich haben möchten public, auch in einer paketprivaten Klasse, müssen Sie später nur noch zur Klassendeklaration hinzufügen public, um die Klasse öffentlich zu machen .

Welche bewährten Methoden gibt es schließlich zu befolgen?

Das ist Ansichtssache und daher für eine Frage oder Antwort zum Stapelüberlauf nicht gut geeignet. Tun Sie, was Ihnen und / oder Ihrem Team vernünftig erscheint, und / oder tun Sie, was Ihnen der Styleguide Ihres Teams vorschreibt.

TJ Crowder
quelle