web-dev-qa-db-ja.com

クラスを保護対象として定義できないのはなぜですか?

私はこれが愚かな質問であることを知っていますが、まだ解決する必要がある疑問があります。

私の質問は、クラスをprotected?として定義できない理由です。

できないことは知っていますが、なぜですか?何らかの特定の理由があるはずです。

72
M.J.

意味がないからです。

保護されたクラスメンバー(メソッドまたは変数)は、サブクラスからもアクセスできることを除いて、package-private(デフォルトの可視性)と同じです。
Javaには「サブパッケージ」や「パッケージ継承」などの概念がないため、class protectedまたはpackage-privateを宣言することも同じことです。

ただし、ネストされたクラスと内部クラスを保護またはプライベートとして宣言できます。

86
Nikita Rybak

ご存じのように、デフォルトはパッケージレベルのアクセス用であり、protectedはパッケージレベルと非パッケージクラス用ですが、このクラスを拡張します(ここで注意すべき点は、クラスが表示されている場合にのみクラスを拡張できることです!)。このようにしてみましょう:

  • 保護された最上位クラスは、パッケージ内のクラスに表示されます。
  • 現在、パッケージ(サブクラス)の外部で表示できるようにするのは少し混乱し、注意が必要です。保護されたクラスを継承できるクラスはどれですか?
  • すべてのクラスがサブクラス化を許可されている場合、パブリックアクセス指定子に似ています。
  • ない場合は、デフォルトに似ています。

このクラスをサブクラス化するのを少数のクラスのみに制限する方法がないため(パッケージ/パッケージの外部で使用可能なすべてのクラスのうち、少数のクラスにのみ継承されるクラスを制限することはできません)、保護されたアクセス指定子の使用はありませんトップレベルのクラス用。したがって、許可されていません。

35
Akash5288
public class A
{
    protected class B
    {
    }
}
13
irreputable

保護されたフィールドを定義すると、そのフィールドはパッケージ内および継承のみでパッケージの外部からアクセス可能になります(子クラス内のみ)。

したがって、クラスを保護することが許可されている場合、パッケージ内で非常に簡単にアクセスできますが、パッケージ外でそのクラスにアクセスするには、最初にこのクラスが定義されているエンティティであるパッケージを拡張する必要があります.

また、パッケージは拡張できない(インポートできる)ため、保護されたクラスを定義すると、パッケージプライベートになります。これは、既に実行できるデフォルトとして定義するのと似ています。したがって、クラスをプライベートに定義しても、物事が曖昧になるだけのメリットはありません。

詳細については、 外部Javaクラスをプライベートまたは保護できない

3
Naresh Joshi

@ Nikita Rybak answer 良い点はありますが、詳細がありません。自分自身を深く考えずに単純にアイデアを得ることができません。

4つのアクセス修飾子。1番目のレベルがパブリックであり、4番目のレベルがプライベートであると仮定します(これに基づいて table に)。最初に知っておくべきことは、クラスがトップレベルでプライベートとして定義できない理由です。

「private class foo」(プライベートメンバーが定義されている、つまりクラス自体がメンバーである)が許可されている場合、アウター(メンバーを含む)は何ですか? ファイルスコープ?いいえ、単一ファイル内の複数のクラスでさえ、別々のクラスファイルにコンパイルされるため、ファイルアウターは無意味です。 つまり、外側はパッケージです。しかし、第3レベルデフォルトのアクセス修飾子は、すでに "package-private"を意味しています。そのため、第4レベルのプライベートアクセス修飾子は使用/許可されません。

しかし、直接の外部はパッケージではなくクラスであるため、ネストされたプライベートクラスは許可されます e.g。

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

「保護されたクラスfoo」が許可されたらどうなりますか?保護主な特性はサブクラスであるため、outer(package)SHOULD(スコープの範囲内ですが、それでもオプションです)style of subclass、つまりサブパッケージ、または package A extends package B、しかし、我々はそのようなことを知りません。 protectedは、外部がパッケージであるトップレベル(つまり、そのようなサブパッケージのものではない)で全潜在能力(メインスコープはサブクラス全体)を使用できませんが、protectedは、外側はクラスです(つまり、サブクラスにすることができます)

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

上記は「外側のサブクラスがないためにサブクラス全体に到達できないため、「完全な可能性を使用できない」と言われていることに注意してください。つまり、実際に保護できるそれはただサブクラス化できない外側の場合にpackage-privateのジョブの重複を避けるための選択の問題、以下を参照してください。

私の混乱は主に https://docs.Oracle.com/javase/tutorial/Java/javaOO/accesscontrol.html の有名なテーブルが原因です。

enter image description here

1番目のレベル(パブリック)と3番目のレベル(パッケージプライベート)が許可されている場合、一体どのように2番目のレベル(保護)が許可されないのですか?

誤解を招きやすいパブリックサポートサブクラス。この表を読む正しい方法は

アウターにサブクラス機能がある場合、サブクラスをパブリックサポートします。

Package-privateにも同じ誤解を招きますが、package-privateはサブクラスをサポートしていません([〜#〜] n [〜#〜] cell)は、サブクラスの概念が外部に適用されることを意味しません。

これは、サブクラス機能が外部で利用できない場合、Subclass列を無視する必要があることを意味します。

enter image description here

ご覧のとおり、protectedとpackage-privateの両方が同じレベルになりました(Y-Y-N)。中間レベルが許可されない理由についてこれ以上混乱はありません。全体として、Java混乱を避けるために保護されたパッケージプライベートのみを選択します(選択の問題ですが、保護されています主な特性はサブクラスです、したがってpackage-privateの方が優れています)、および result 、トップレベルで許可されるアクセス修飾子は2つのみです:

最上位レベル-パブリック、またはパッケージプライベート(明示的な修飾子なし)。

2
林果皞

保護は一般公開とは異なります。 Protectedは、パッケージレベルのアクセスに加えて、継承によってのみパッケージの外部にアクセスできます。クラスがパッケージの外部のAが他のパッケージのクラスを継承する場合(INHERITANCEを使用したprotectedメソッドを使用)、このクラスBのメソッドにアクセスできますは保護されたメソッドを持っていますが、このクラスから派生したサブクラス、つまりAは保護されたメソッドにアクセスできません。

例:

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
}
1
Shruthi reddy

「保護」の動作=「デフォルト」の動作+「パッケージ内のサブクラスで使用」。

とにかく、クラスにデフォルトのアクセス修飾子がありますが、保護されたアクセス修飾子から得られる利点は次のとおりです。ただし、サブクラスの場合、親「保護」クラスの可視性はプライベートになります。そのため、アクセスできません。基本的に、保護されたトップレベルクラスがある場合、外部クラスはサブクラス化してアクセスできません。したがって、最上位クラスの保護は無意味です。

0
madhu

protectedは、同じパッケージ内の任意のクラスおよびサブクラスが別のパッケージ内にある場合でも、メンバーにアクセスできることを意味します。

例:

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
Yogesh Patil

この質問に理にかなっているのは、JVMはC(Sun JVM)およびC++(Oracle JVM)で記述されているため、コンパイル中にJavaファイルから.classファイルを作成するということです。 Protectedキーワードを使用してクラスを宣言すると、JVMからアクセスされなくなります。

保護されたクラスがJVMによってアクセスされない理由は、保護されたフィールドは同じパッケージ内または継承を通じてのみ異なるパッケージにアクセス可能であり、JVMはwillクラスを継承するように書かれていないためです。これがこの質問を満たすことを願っています:)

同様に、最上位クラスをプライベートにすることはできません。以下の説明:

では、クラスprivateを定義すると、そのクラスは、それが定義されているエンティティ(この場合はパッケージ)内でのみアクセス可能になります。

そのため、クラスへのプライベートアクセスを定義すると、デフォルトのキーワードがすでに行っている同じパッケージ内でアクセスできるようになります。したがって、クラスをプライベートに定義しても利点はありません。

0
Anurag Prasad

@ Akash5288からの答えは私には意味がありませんでした:

すべてのクラスがサブクラス化を許可されている場合、パブリックアクセス指定子に似ています。

このクラスをサブクラス化するのを少数のクラスのみに制限する方法がないため(パッケージ/パッケージの外部で使用可能なすべてのクラスのうち、少数のクラスにのみ継承されるクラスを制限することはできません)、保護されたアクセス指定子の使用はありませんトップレベルのクラス用。したがって、許可されていません。

その後、同じロジックを保護されたメソッドと変数に適用できます。これらは「パブリックに似ています」。パッケージ外のすべてのクラスは、パブリッククラスを拡張し、その保護されたメソッドを使用できます。メソッドと変数を拡張クラスに制限してもよいのに、クラス全体を制限できないのはなぜですか? 「公共に類似」は「公共と同じ」ではありません。私の解釈では、保護されたメソッドを許可することは問題ないので、保護されたクラスを許可することはまったく問題ありません。

「アクセス/参照できないクラスを拡張することはできません」という答えは、より論理的です。

0
k-s

保護:パッケージレベルのみに表示*。

クラスは定義済みprotected ---> it 拡張不可パッケージ外から(見えない)。

拡張できない場合、protectedのままにしておくことは無意味です。なぜなら、default許可されるアクセス。

同じことがprivate定義されたクラスに適用されます。

注:入れ子または内部クラスを定義できますprotectedまたはprivate

*:探索protectedキーワード、この答えのために簡潔にしました。

0
Narendra Singh