Domanda metodi pubblici in classi pacchetto-private


Fa la differenza per marcare metodi come public in classi private di pacchetti?

class SomePackagePrivateClass
{
    void foo();          // package private method

    public void bar();   // public method
}

C'è qualche differenza pratica nella visibilità tra foo e bar Qui?


31
2018-03-10 13:49


origine


risposte:


Se la classe non verrà estesa da un'altra sottoclasse * più visibile, l'unica differenza è chiarezza d'intenti. Dichiarare tutti i pacchetti di metodi privati ​​rende più difficile per i futuri lettori determinare quale dei metodi sia chiamato ad essere chiamato da altre classi nello stesso pacchetto.

*che non avrebbe molto senso come soluzione progettuale per me, ma tecnicamente è comunque possibile.


16
2018-03-10 13:52



Esempio utilizzando l'ereditarietà:

A.java

package pkg1

class A {
  void foo();
  public void bar() {};
}

B.java

package pkg1

public class B extends A{

}

C.java

package pkg2

public class C {
  public void doSomething() {
   B b = new B();
   b.bar(); //ok
   b.foo(); //won't work, since foo() is not visible outside of package 'pkg1'

   A a = new A(); //won't work since A is not visible outside of package 'pkg1'
   a.bar(); //won't work, since a cannot be created
  }
}

36
2018-03-10 14:15



Un altro caso in cui il metodo deve essere pubblico è quando si crea un'implementazione privata di un pacchetto di qualche classe pubblica o interfaccia. Poiché non ti è consentito ridurre la visibilità dei metodi sottoposti a override, questi devono essere pubblici.


9
2018-03-10 14:39



Beh ... avevo anche questo dubbio (è per questo che ho cercato questo thread). Questa potrebbe essere una buona domanda.

Ma ...

Dopo un secondo pensiero, le cose sono davvero più semplici di quanto pensassimo.

Un metodo package-private, è un metodo package-private.

Sembra una sciocchezza? Ma ...

Un metodo package-private, anche se la sua classe è ereditata, lo è ancora un metodo package-private.

Ha più senso ora? Per una spiegazione più dettagliata:

Un metodo package-private, anche se la sua classe è ereditata da una sottoclasse più visibile, lo è ancora un metodo package-private.

  Se la sottoclasse è dello stesso pacchetto, anche questi metodi del pacchetto-privato vengono ereditati, ma sono ancora pacchetti-privati.

  Se la sottoclasse è del diverso pacchetto (di qui, abbiamo bisogno che la classe genitrice sia pubblica, con alcuni metodi package-private), quei metodi package-private sono non ereditato (perché non sono affatto visibili).

  Un punto da notare, che potrebbe essere la causa di questo dubbio, è che un metodo package-private in una public class non è visibile anche fuori dal pacchetto.


Quanto sopra spiega il metodo package-private. E il caso del metodo pubblico è lo stesso.

Quando una classe pacchetto-privata è ereditata da una sottoclasse pubica (dello stesso pacchetto, questo è un must), i suoi metodi pubblici sono ereditati come metodi pubblici e quindi diventano metodi pubblici in una classe pubblica.

Nell'esempio OP, come foo() e bar() sono entrambi in una classe package-private, le loro visibilità sono limitate al pacchetto-private in questo momento, fino a quando non vengono aggiunti ulteriori codici (ad esempio l'ereditarietà).

Spero che questo sia chiaro (e semplice) abbastanza.

Post scriptum la tabella di controllo degli accessi Java


6
2018-05-14 18:08



Fa poca differenza, a meno che la classe non sia estesa da una classe pubblica (o nidificata protetta).

Per una questione di coerenza, mi piacerebbe andare public. Dovrebbe essere raro che i metodi siano qualcosa di diverso da publico private.

Esistono numerosi esempi di metodi pubblici nel pacchetto privato java.lang.AbstractStringBuilder classe. Per esempio length() è pubblico in AbstractStringBuilder ed è esposto nella classe pubblica StringBuilder (sovrascritto in StringBuffer per aggiungere la sincronizzazione).


5
2018-03-10 13:50



Sì. public i metodi in una classe pacchetto-privata possono essere utili. Esempio illustrativo dalla libreria java (e tratto dal classico "java efficace"):

Hai mai visto il java.util.JumboEnumSet, java.util.RegularEnumSet?? Probabilmente no, perché sono privati ​​e non sono indicati nella documentazione.

Li hai mai usati ?? Probabilmente sì. Sono restituiti dal metodo statico di java.util.EnumSet.noneOf(...). Sebbene non sia possibile costruirli da soli, è possibile utilizzare i loro metodi pubblici quando vengono restituiti da questo metodo.

La cosa buona è che non sai quale stai usando, o anche che esistono. Java decide quale è più efficiente a seconda degli argomenti, e potrebbe utilizzare un altro in una versione più recente. Accedi alle loro funzionalità solo facendo riferimento ad esse attraverso la loro interfaccia comune (che comunque è una buona pratica !!)


2
2017-12-22 11:25



foo ha default package visibility mentre bar ha public visibilità


-1
2018-03-10 13:51