Warum kann eine Klasse nicht als geschützt definiert werden?


86

Warum können wir eine Klasse nicht als definieren protected?

Ich weiß, dass wir nicht können, aber warum? Es sollte einen bestimmten Grund geben.


3
Was würde es tun, wenn Sie eine Klasse als geschützt deklarieren würden ?


2
Sagen wir einfach, warum die äußere Klasse nicht geschützt werden kann. Innere Klassen können geschützt werden.
Nummer 945

Antworten:


97

Weil es keinen Sinn macht.

Geschütztes Klassenmitglied (Methode oder Variable) ist genau wie package-private (Standardsichtbarkeit), außer dass auch über Unterklassen darauf zugegriffen werden kann.
Da es in Java kein Konzept wie "Unterpaket" oder "Paketvererbung" gibt, wäre es dasselbe, deklarationsgeschützt oder paketprivat zu deklarieren.

Sie können jedoch verschachtelte und innere Klassen als geschützt oder privat deklarieren.


> Da es in Java kein Konzept wie "Unterpaket" oder "Paketvererbung" gibt, wäre es dasselbe, deklarationsgeschützt oder paketprivat zu deklarieren. Warum hat eine geschützte Klasse die gleiche Sichtbarkeit wie package-private? Ist es nicht dasselbe wie öffentlich? Vielen Dank.
Yaromir

@Nikita Ryback Können Sie erklären, was SubPackage oder Paketvererbung ist? Ich bin mir immer noch nicht sicher, warum protected in der Klasse der obersten Ebene verwendet wird. Wenn Sie dies anhand eines Beispiels erklären, ist das großartig.
App Kart

Wenn Sie ein Klassenmitglied als geschützt deklarieren, werden Klassen desselben Pakets (als Paketzugriff bezeichnet) und der Unterklasse angezeigt . Wenn Sie versuchen, von einer Outter-Klasse in einem anderen Paket aus zuzugreifen, ist dieses geschützte Methodenmitglied nicht sichtbar.
Kelgwiin

@kelgwiin Ich glaube, Sie sollten Zugriffsmodifikatoren von Klassen und Mitgliedern nicht mischen. Weil die beiden unterschiedlich sind. Während Klassen sich als öffentlich oder standardmäßig ändern lassen, können die Mitglieder als öffentlich, privat, geschützt und standardmäßig geändert werden.
Sharhp

2
"Weil es keinen Sinn macht" - das ist eine ziemlich kühne Aussage. Es ist nicht in Java definiert, aber ähnliche Dinge tun existieren; zB openin Kotlin, das eine Unterklasse außerhalb des aktuellen Pakets erlaubt (man könnte sich vorstellen protected, dass dies in Java verhindert wird, mit der entgegengesetzten Standardeinstellung).
Raphael

41

Wie Sie wissen, gilt die Standardeinstellung für den Zugriff auf Paketebene und geschützt für die Paketebene plus Nicht-Paketklassen, die diese Klasse jedoch erweitern (Beachten Sie hier, dass Sie die Klasse nur erweitern können, wenn sie sichtbar ist!). Sagen wir es so:

  • Eine geschützte Klasse der obersten Ebene wäre für die Klassen in ihrem Paket sichtbar.
  • Jetzt ist es etwas verwirrend und schwierig, es außerhalb des Pakets (Unterklassen) sichtbar zu machen. Welche Klassen dürfen unsere geschützte Klasse erben?
  • Wenn alle Klassen eine Unterklasse haben dürfen, ähnelt dies dem Public Access Specifier.
  • Wenn keine vorhanden ist, ähnelt dies der Standardeinstellung.

Da es keine Möglichkeit gibt, die Unterklasse dieser Klasse durch nur wenige Klassen einzuschränken (wir können nicht einschränken, dass nur wenige Klassen von allen verfügbaren Klassen in einem Paket / außerhalb eines Pakets geerbt werden), werden keine geschützten Zugriffsspezifizierer verwendet für Top-Level-Klassen. Daher ist es nicht erlaubt.


3
"Jetzt ist es etwas verwirrend und schwierig, eine geschützte Klasse außerhalb des Pakets (Unterklassen) sichtbar zu machen. Welche Klassen sollten unsere geschützte Klasse erben dürfen? Wenn alle Klassen Unterklassen dürfen, ähnelt sie dem Public Access Specifier." hat mir wirklich geholfen, das Problem zu verstehen, warum geschützte Klassen keinen Sinn ergeben :)
user1338998


3

Durch das Definieren eines geschützten Felds kann auf dieses Feld sowohl innerhalb des Pakets als auch außerhalb des Pakets nur durch Vererbung zugegriffen werden (nur innerhalb der untergeordneten Klasse).

Wenn wir also eine Klasse schützen dürfen, können wir sehr einfach innerhalb des Pakets darauf zugreifen. Um jedoch auf diese Klasse außerhalb des Pakets zugreifen zu können, müssen wir zuerst die Entität erweitern, in der diese Klasse definiert ist, nämlich das Paket.

Und da ein Paket nicht erweitert werden kann (importiert werden kann), wird es durch das Definieren einer geschützten Klasse wieder paketprivat, was dem Definieren als Standard ähnelt, was wir bereits tun können. Daher hat die Definition einer privaten Klasse keinen Vorteil, da sie die Dinge nur mehrdeutig macht.

Weitere Informationen finden Sie unter Warum eine äußere Java-Klasse nicht privat oder geschützt sein kann


3
Bitte legen Sie jegliche Zugehörigkeit offen und verwenden Sie die Website nicht, um Ihre Website durch Veröffentlichung zu bewerben. Siehe Wie schreibe ich eine gute Antwort? .

2

@ Nikita Rybak Antwort hat gute Punkte, aber Mangel an Details, ich kann nicht einfach auf die Idee kommen, ohne tief selbst nachzudenken, das Folgende ist, was ich dachte und jetzt sollte ich den Grund vollständig verstehen.

Bei vier Zugriffsmodifikatoren wird davon ausgegangen, dass die 1. Ebene öffentlich und die 4. Ebene privat ist (basierend auf dieser Tabelle nacheinander). Das erste, was wir wissen sollten, ist, warum Klasse auf oberster Ebene nicht als privat definiert werden kann.

Also, wenn "private class foo" (ein privates Mitglied definiert, dh die Klasse selbst ist ein Mitglied) erlaubt, was ist das Äußere (das das Mitglied enthält)? Dateibereich? Nein, die äußere Datei ist sinnlos, da sogar mehrere Klassen in einer Datei in separate Klassendateien kompiliert werden. Das Äußere ist also ein Paket . Der Standardzugriffsmodifikator der 3. Ebene bedeutet jedoch bereits "paketprivat ". Daher wird der Modifikator für den privaten Zugriff der 4. Ebene nicht verwendet / zugelassen.

Eine verschachtelte private Klasse ist jedoch zulässig, da die direkte äußere Klasse eine Klasse ist, kein Paket, z .

class PrivateNestedMain {
    private static class Inner {
        public static void main(String[] args) {
            System.out.println("Hello from Inner!");
        }
    }
}

Was ist nun, wenn "protected class foo" dies zulässt? Das geschützte Hauptmerkmal ist die Unterklasse, daher sollte das äußere (Paket) (aufgrund des Umfangs, aber immer noch optional) den Stil der Unterklasse , dh des Unterpakets, oder package A extends package B, aber wir wissen nichts davon, angeben. So kann protected nicht das volle Potenzial (der Hauptbereich ist unterklassenweit) in der obersten Ebene nutzen, in der das äußere Paket enthalten ist (dh keine solche Unterpaket-Sache), aber protected kann das volle Potenzial in verschachtelten Klassen nutzen, in denen das äußere Paket ist ( dh kann Unterklasse sein) :

class ProtectedNestedMain {
    protected static class Inner {
        public static void main(String[] args) {
            System.out.println("Hello from Inner!");
        }
    }
}

Beachten Sie, dass das oben Gesagte "kann nicht das volle Potenzial ausschöpfen", da es nicht die gesamte Unterklasse erreichen kann, nur weil keine äußere Unterklasse vorhanden ist. Dies bedeutet, dass tatsächlich geschützt werden kann . Es ist nur eine Frage der Wahl, um zu vermeiden, dass der Job des Pakets doppelt ausgeführt wird -privat, wenn äußere nicht unterklassenfähig sind , siehe unten.

Meine Verwirrung wird hauptsächlich durch die berühmte Tabelle unter https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html verursacht :

Geben Sie hier die Bildbeschreibung ein

Wenn die 1. Ebene (öffentlich) und die 3. Ebene (paketprivat) erlaubt sind, wie um alles in der Welt ist die dazwischen liegende 2. Ebene (geschützt) nicht erlaubt?

öffentliche Unterstützung Unterklasse so leicht irreführend. Die richtige Art, diese Tabelle zu lesen, ist

öffentliche Unterstützungsunterklasse, wenn die äußere Unterklassenfunktion hat.

Die gleiche Irreführung gilt für package-private, package-private unterstützt keine Unterklasse ( N in Zelle) bedeutet nicht, dass das Unterklassenkonzept in Outer gilt.

Dass die Mittel sollten wir die ignorieren Subklassen - Spalte , wenn Unterklasse - Funktion nicht verfügbar in Außen ist:

Geben Sie hier die Bildbeschreibung ein

Wie wir jetzt sehen können, sind sowohl geschützt als auch paketprivat jetzt dieselbe Ebene ( YYN ), keine Verwirrung mehr darüber, warum eine Zwischenebene nicht zulässig ist. Insgesamt wählt Java nur package-private über protected aus, um Verwirrung zu vermeiden ( es ist nur eine Frage der Wahl , aber das geschützte Hauptmerkmal ist die Unterklasse, sodass package-private überlegen ist), und das Ergebnis sind nur 2 Zugriffsmodifikatoren in der obersten Ebene zulässig:

Auf der obersten Ebene - öffentlich oder paketprivat (kein expliziter Modifikator).


1

Geschützt ist nicht ähnlich wie öffentlich. Protected verfügt über Zugriff auf Paketebene und kann nur durch Vererbung außerhalb von Paketen aufgerufen werden. Wenn eine Klasse sagt, dass A außerhalb eines Pakets eine Klasse aus einem anderen Paket erbt (mit geschützter Methode unter Verwendung von INHERITANCE), kann sie auf die Methoden dieser Klasse B zugreifen, die hat geschützte Methoden, aber die von dieser Klasse abgeleiteten Unterklassen, dh A kann nicht auf die geschützten Methoden zugreifen. Das Gegenteil passiert mit public.

Beispiel:

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

Verhalten von "protected" = Verhalten von "default" + "Verwenden Sie es in einer beliebigen Unterklasse in einem beliebigen Paket".

Wie auch immer, wir haben einen Standardzugriffsmodifikator für die Klasse. Der einzige Vorteil, den wir durch einen geschützten Zugriffsmodifikator erhalten können, ist: - indem wir ihn in einem beliebigen Paket durch Unterklassen verwenden. Für die Unterklasse wäre die Sichtbarkeit der übergeordneten "geschützten" Klasse jedoch privat. Es kann also nicht darauf zugegriffen werden. Wenn Sie über eine geschützte Klasse der obersten Ebene verfügen, kann grundsätzlich keine äußere Klasse durch Unterklasse darauf zugreifen. So geschützt für eine Top-Level-Klasse ist bedeutungslos.


0

Geschützt : Nur auf Paketebene * SICHTBAR.

Klasse ist als geschützt definiert ---> sie kann nicht von außerhalb des Pakets erweitert werden (nicht sichtbar).

Und wenn es nicht erweitert werden kann, ist es sinnlos, es als geschützt zu betrachten , da es dann zum Standardzugriff wird, der zulässig ist.

Gleiches gilt für privat definierte Klassen.

Hinweis: Verschachtelte oder innere Klassen können geschützt oder privat definiert werden .

* : Erkunde geschütztes Schlüsselwort, für diese Antwort habe ich es kurz und bündig gemacht.


0

Die Antwort von @ Akash5288 ergab für mich keinen Sinn:

Wenn alle Klassen eine Unterklasse haben dürfen, ähnelt dies dem Public Access Specifier.

Da es keine Möglichkeit gibt, die Unterklasse dieser Klasse durch nur wenige Klassen einzuschränken (wir können nicht einschränken, dass nur wenige Klassen von allen verfügbaren Klassen in einem Paket / außerhalb eines Pakets geerbt werden), werden keine geschützten Zugriffsspezifizierer verwendet für Top-Level-Klassen. Daher ist es nicht erlaubt.

Sie können dann dieselbe Logik auf geschützte Methoden und Variablen anwenden, sie sind dann auch "ähnlich wie öffentlich". Alle Klassen außerhalb eines Pakets können unsere öffentliche Klasse erweitern und ihre geschützten Methoden verwenden. Warum ist es in Ordnung, Methoden und Variablen auf erweiterte Klassen zu beschränken, aber die gesamte Klasse nicht einzuschränken? "Ähnlich wie öffentlich" ist nicht "gleich wie öffentlich". Meine Interpretation ist, dass es vollkommen in Ordnung ist, eine geschützte Klasse zuzulassen, da es in Ordnung ist, geschützte Methoden zuzulassen.

Die Antwort "Sie können eine Klasse, auf die Sie nicht zugreifen / die Sie nicht sehen können, nicht erweitern" ist logischer.


0

Was für diese Frage Sinn macht, ist, dass JVM in C (Sun JVM) und C ++ (Oracle JVM) geschrieben ist. Während der Kompilierung werden wir .class-Dateien aus unserer Java-Datei erstellen und eine Klasse mit dem Schlüsselwort Protected deklarieren dann wird von JVM nicht darauf zugegriffen.

Die Antwort, warum JVM nicht auf geschützte Klassen zugreifen kann, lautet: Da auf geschützte Felder innerhalb desselben Pakets oder auf andere Pakete nur durch Vererbung zugegriffen werden kann und JVM nicht so geschrieben ist, dass es Willensklassen erbt. Hoffe das befriedigt diese Frage :)

Ebenso kann eine Klasse der obersten Ebene nicht privat sein. Erklärung wie folgt:

Was passiert also, wenn wir eine private Klasse definieren? Auf diese Klasse kann nur innerhalb der Entität zugegriffen werden, in der sie definiert ist. In unserem Fall handelt es sich um ihr Paket.

Wenn Sie also den privaten Zugriff auf die Klasse definieren, wird sie innerhalb desselben Pakets zugänglich, das das Standardschlüsselwort bereits für uns verwendet. Daher ist es nicht vorteilhaft, eine private Klasse zu definieren, da die Dinge nur mehrdeutig werden.


0

Geschützt bedeutet, dass auf das Mitglied von jeder Klasse im selben Paket und von Unterklassen zugegriffen werden kann, selbst wenn sie sich in einem anderen Paket befinden.

Beispiel:

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 
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.