Perché non possiamo definire una classe come protected
?
So che non possiamo, ma perché? Ci dovrebbe essere un motivo specifico.
Perché non possiamo definire una classe come protected
?
So che non possiamo, ma perché? Ci dovrebbe essere un motivo specifico.
Risposte:
Perché non ha senso.
Il membro della classe protetto (metodo o variabile) è proprio come il pacchetto privato (visibilità predefinita), tranne per il fatto che è possibile accedervi anche dalle sottoclassi.
Poiché in Java non esiste alcun concetto come "sottopacchetto" o "ereditarietà del pacchetto", dichiarare la classe protetta o privata del pacchetto sarebbe la stessa cosa.
Tuttavia, puoi dichiarare classi nidificate e interne come protette o private.
open
in Kotlin che consente la creazione di sottoclassi al di fuori del pacchetto corrente (si potrebbe immaginare che protected
in Java lo prevenga, con il valore predefinito opposto).
Come sapete l'impostazione predefinita è per l'accesso a livello di pacchetto e protetta è per il livello di pacchetto più classi non di pacchetto, ma che estende questa classe (il punto da notare qui è che puoi estendere la classe solo se è visibile!). Mettiamola in questo modo:
Poiché non c'è modo di limitare questa classe a essere sottoclasse solo da poche classi (non possiamo limitare la classe che viene ereditata solo da poche classi su tutte le classi disponibili in un pacchetto / al di fuori di un pacchetto), non c'è uso di specificatori di accesso protetto per classi di alto livello. Quindi non è consentito.
public class A
{
protected class B
{
}
}
La risposta di @Nikita Rybak ha buoni punti ma mancanza di dettagli, non posso semplicemente avere l'idea senza pensarci profondamente, quanto segue è quello che ho pensato e ora dovrei capire completamente il motivo.
Quattro modificatori di accesso, assumono che il 1 ° livello sia pubblico e il 4 ° livello sia privato (in base a questa tabella in sequenza). La prima cosa che dovremmo sapere è perché la classe non può essere definita come privata nel primo livello.
Quindi, se "private class foo" (un membro privato definito, cioè la classe stessa è un membro) lo consente, qual è l'esterno (che contiene il membro)? Ambito del file? No, il file esterno è inutile perché anche più classi in un singolo file verranno compilate in file di classe separati. Quindi l'esterno è il pacchetto . Ma il modificatore di accesso predefinito di 3 ° livello significa già "pacchetto privato ". Quindi il modificatore di accesso privato di 4 ° livello non sarà utilizzato / consentito.
Ma la classe privata annidata è consentita perché l'esterno diretto è la classe, non il pacchetto, ad esempio :
class PrivateNestedMain {
private static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
E se la "classe protetta pippo" lo permettesse? La caratteristica principale protetta è la sottoclasse, quindi il (pacchetto) esterno DOVREBBE (a causa dell'ambito fino a, ma è comunque opzionale) fornire lo stile della sottoclasse , cioè il sotto-pacchetto, o package A extends package B
, ma non sappiamo nulla del genere. Quindi protected non può utilizzare il pieno potenziale (l'ambito principale è a livello di sottoclasse) nel livello superiore che l'esterno è il pacchetto (cioè nessuna cosa del sotto-pacchetto), ma protected può usare tutto il potenziale nella classe annidata che l'esterno è class ( ie può essere una sottoclasse) :
class ProtectedNestedMain {
protected static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
Nota che quanto sopra detto "non può usare il pieno potenziale" perché non può raggiungere l'intera sottoclasse semplicemente perché nessuna sottoclasse esterna, ciò significa che può essere effettivamente protetta , è solo una questione di scelta evitare di duplicare il lavoro del pacchetto -privato se esterno non è sottoclasse , vedi sotto.
La mia confusione è principalmente causata dalla famosa tabella su https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html :
Se il 1 ° livello (pubblico) e il 3 ° livello (pacchetto privato) sono consentiti, come mai il 2 ° livello intermedio (protetto) non è consentito?
sottoclasse di sostegno pubblico così facile da fuorviare. Il modo corretto per leggere questa tabella è
sottoclasse di supporto pubblico se l'esterno ha la funzione di sottoclasse.
Lo stesso fuorviante si applica a pacchetto-privato, pacchetto-privato non supporta la sottoclasse ( N nella cella) non significa che il concetto di sottoclasse si applica in esterno.
Ciò significa che dovremmo ignorare la colonna Sottoclasse se la funzione sottoclasse non è disponibile in esterno:
Come possiamo vedere ora, sia il livello protetto che quello privato del pacchetto sono allo stesso livello ora ( YYN ), non c'è più confusione sul motivo per cui il livello intermedio non è consentito. Nel complesso, Java sceglie solo il pacchetto privato rispetto a quello protetto per evitare confusione ( è solo una questione di scelta , ma la caratteristica principale protetta è la sottoclasse, quindi il pacchetto privato è superiore), e il risultato , solo 2 modificatori di accesso consentiti nel livello superiore:
Al livello superiore: pubblico o pacchetto privato (nessun modificatore esplicito).
La definizione di un campo protetto rende quel campo accessibile sia all'interno del pacchetto che all'esterno del pacchetto solo tramite ereditarietà (solo all'interno della classe figlia).
Quindi, se ci è permesso rendere una classe protetta, allora possiamo accedervi all'interno del pacchetto molto facilmente, ma per accedere a quella classe al di fuori del pacchetto dobbiamo prima estendere quell'entità in cui è definita questa classe che è il suo pacchetto.
E poiché un pacchetto non può essere esteso (può essere importato), la definizione di una classe protetta la renderà nuovamente privata del pacchetto, il che è simile alla definizione di default che possiamo già fare. Quindi non vi è alcun vantaggio nel definire una classe privata, renderà solo le cose ambigue.
Per ulteriori informazioni, leggi Perché una classe Java esterna non può essere privata o protetta
Protetto non è simile al pubblico. Protected ha sia l'accesso a livello di pacchetto che l'accesso all'esterno dei pacchetti solo per ereditarietà .. Se una classe dice A all'esterno di un pacchetto Eredita una classe da un altro pacchetto (con metodo protetto utilizzando INHERITANCE) può accedere ai metodi di questa classe B che ha metodi protetti ma le sottoclassi derivate da questa classe, cioè A non può accedere ai metodi protetti..il contrario accade con public ..
Esempio:
package 2;
class B
{
protected void method1()
{
}
}
package 1;
import 2.B;
class A extends B
{
//can access protected method
}
class C extends A
{
//can't access the protected method
}
comportamento di "protected" = comportamento di "default" + "usalo in qualsiasi sottoclasse in qualsiasi pacchetto".
Ad ogni modo abbiamo un modificatore di accesso predefinito per la classe, l'unico vantaggio che possiamo ottenere dal modificatore di accesso protetto è: - usandolo in qualsiasi pacchetto tramite sottoclassi. Ma per la sottoclasse, la visibilità della classe genitore "protetta" sarebbe privata. Quindi non è possibile accedervi. Fondamentalmente, se hai una classe di primo livello protetta, nessuna classe esterna può ottenere l'accesso sottoclassandola. Così protetto per una classe di primo livello non ha senso.
Protetto : VISIBILE solo a livello di pacchetto *.
la classe è definita protetta ---> non può essere estesa dall'esterno del pacchetto (non visibile).
E se non può essere esteso, non ha senso mantenerlo protetto , perché diventerà predefinito accesso consentito.
Lo stesso vale per le classi definite private .
Nota: le classi nidificate o interne possono essere definite protette o private .
* : Esplora la parola chiave protetta , per questa risposta l'ho resa succinta.
La risposta di @ Akash5288 non aveva senso per me:
Se tutte le classi possono essere sottoclasse, sarà simile allo specificatore di accesso pubblico.
Poiché non c'è modo di limitare questa classe a essere sottoclasse solo da poche classi (non possiamo limitare la classe che viene ereditata solo da poche classi su tutte le classi disponibili in un pacchetto / al di fuori di un pacchetto), non c'è uso di specificatori di accesso protetto per classi di alto livello. Quindi non è consentito.
È quindi possibile applicare la stessa logica a metodi e variabili protetti, che sono anche "simili a pubblici". Tutte le classi esterne a un pacchetto possono estendere la nostra classe pubblica e utilizzare i suoi metodi protetti. Perché limitare metodi e variabili a classi estese va bene, ma limitare l'intera classe non va bene? "Simile a pubblico" non è "uguale a pubblico". La mia interpretazione è che va perfettamente bene consentire una classe protetta, così come va bene consentire metodi protetti.
La risposta "non puoi estendere una classe a cui non puoi accedere / vedere" è più logica.
Ciò che ha senso a questa domanda è che, JVM è scritto in C (Sun JVM) e C ++ (Oracle JVM) quindi durante la compilazione, creeremo file .class dal nostro file java e se dichiariamo una classe con la parola chiave protetta quindi non sarà accessibile da JVM.
La risposta al motivo per cui JVM non accederà alla classe protetta è che, poiché i campi protetti sono accessibili all'interno dello stesso pacchetto o in un pacchetto diverso solo attraverso l'ereditarietà e la JVM non è scritta in modo tale da ereditare la classe. Spero che questo soddisfi questa domanda :)
Allo stesso modo, una classe di primo livello non può essere privata. Spiegazione come di seguito:
Quindi cosa succederà se definiremo una classe privata, quella classe sarà accessibile solo all'interno dell'entità in cui è definita che nel nostro caso è il suo pacchetto?
Quindi definire l'accesso privato alla classe lo renderà accessibile all'interno dello stesso pacchetto che la parola chiave predefinita già fa per noi, quindi non c'è alcun vantaggio nel definire una classe privata, renderà solo le cose ambigue.
protetto significa che è possibile accedere al membro da qualsiasi classe nello stesso pacchetto e da sottoclassi anche se si trovano in un altro pacchetto.
Esempio:
package a;
class parent{
protected void p();
}
package b;
import a.p;
class child extends parent{
//you can access method which is protected in the parent in the child
}
class another extends child {
//here you can not access the protected method
}
se una classe esterna è dichiarata da protected, penso che tu voglia che la classe sia accessibile solo dallo stesso pacchetto e dalla sua sottoclasse ma pacchetti diversi. Tuttavia, non è possibile creare sottoclassi per una classe protetta, perché quando scrivi "class Dog extends Animal", a causa di "Animal" protetto è possibile accedere solo dalla sua sottoclasse, ovviamente, "Dog" non è la sottoclasse "Animal" .
Quindi la classe esterna protetta è la stessa della classe esterna (predefinita)!