Perché una classe non può essere definita protetta?


91

Perché non possiamo definire una classe come protected?

So che non possiamo, ma perché? Ci dovrebbe essere un motivo specifico.


3
Cosa sarebbe fare se avete dichiarato una classe protetta?


2
Diciamo solo perché la classe esterna non può essere protetta? Le classi interne possono essere protette.
Numero 945

Risposte:


102

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.


> Dato che in Java non esistono concetti come "sottopacchetto" o "ereditarietà del pacchetto", dichiarare la classe protetta o privata del pacchetto sarebbe la stessa cosa. Perché la classe protetta avrebbe la stessa visibilità del pacchetto privato? Non è lo stesso del pubblico? Grazie.
yaromir

@Nikita Ryback Puoi spiegare cos'è il subPackage o l'ereditarietà del pacchetto? Non mi è ancora chiaro perché protetto sia usato nella classe di primo livello. Se spieghi con un esempio, sarà fantastico.
App Kart

Quando si dichiara un membro della classe protetto, la sua visibilità è costituita dalle classi dello stesso pacchetto (chiamato accesso al pacchetto) e dalla sottoclasse . Se si tenta di accedere da una classe outter in un altro pacchetto, questo membro del metodo protetto non è visibile.
kelgwiin

@kelgwiin Credo che non dovresti mescolare i modificatori di accesso delle classi e quello dei membri. Perché i due sono diversi. Mentre le classi consentono di essere modificate come pubbliche o predefinite, i membri possono essere modificati come pubblici, privati, protetti e predefiniti.
sharhp

2
"Perché non ha senso" - questa è un'affermazione piuttosto audace. Non è definito in Java, ma le cose simili non esiste; ad esempio openin Kotlin che consente la creazione di sottoclassi al di fuori del pacchetto corrente (si potrebbe immaginare che protectedin Java lo prevenga, con il valore predefinito opposto).
Raphael

41

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:

  • la classe di primo livello protetta sarebbe visibile alle classi nel suo pacchetto.
  • ora renderlo visibile al di fuori del pacchetto (sottoclassi) è un po 'complicato e complicato. A quali classi dovrebbe essere consentito ereditare la nostra classe protetta?
  • Se tutte le classi sono autorizzate a subclassare, sarà simile allo specificatore di accesso pubblico.
  • Se nessuno, è simile all'impostazione predefinita.

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.


3
"ora rendere visibile una classe protetta al di fuori del pacchetto (sottoclassi) è un po 'complicato e complicato. A quali classi dovrebbe essere consentito ereditare la nostra classe protetta? e se tutte le classi possono essere sottoclasse, allora sarà simile allo specificatore di accesso pubblico." mi ha davvero aiutato a capire il problema del perché le classi protette non hanno senso :)
user1338998


3

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 :

inserisci qui la descrizione dell'immagine

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:

inserisci qui la descrizione dell'immagine

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


3

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


3
Si prega di divulgare eventuali affiliazioni e di non utilizzare il sito come mezzo per promuovere il proprio sito tramite la pubblicazione. Vedi Come scrivo una buona risposta? .

1

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
}

0

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.


0

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.


0

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.


0

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.


0

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 
}

0

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)!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.