8

サブクラスがスーパークラスからプライベートメンバーを継承できないが、ここで説明するように、継承されていないプライベートメンバーにアクセスできるスーパークラスからパブリックメソッドを継承する場合

http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

サブクラスの継承されたメンバーによって変更されたスーパークラスのプライベートメンバーはどこに保存されますか?それらはどこに存在しますか?

4

2 に答える 2

10

プライベートメンバー変数は、それらが宣言されているクラスに存在すると考えてください。サブクラスがメンバー変数を変更する親クラスのメソッドを呼び出す場合、その変更は親クラスで発生していると考えてください。その親クラスだけがその変数の値を読み書きするコードを持つことができるので、これは頭の中でそれをモデル化するための便利な方法です。

サブクラスは親クラスにリクエストを送信し、そこで宣言されたメンバー変数を使用して何かを実行する必要があります。

親クラスのメソッドをサブクラスのコードでオーバーライドすると、親のオーバーライドされたメソッドがアクセスできる場合でも、そのオーバーライドメソッドはプライベートメンバー変数にアクセスできません。ただし、サブクラスのオーバーライドメソッドは、親のオーバーライドメソッドを呼び出すことができます。

例えば:

public class Parent {
    private int bar = 0;
    public void setBar(int value) {
        bar = value;
    }
}

public class Derived extends Parent {
    @override
    public void setBar(int value) {
        bar = value + 1; // NOT ALLOWED
        super.setBar(value + 1); // ALLOWED (same result)
    }
}

低レベル情報:

ただし、低レベルでは、SubClassのインスタンスを作成して、SubClassのすべてのインスタンス変数と、Objectまでのすべての親クラス用のスペースを備えたメモリブロックを割り当てる場合があります。

メソッド自体のコードは、各メソッドを含むクラスのClassLoaderによって割り当てられたメモリにあります。これは、クラスごとに割り当てられます。したがって、データがインスタンスに一緒に保存されていても、さまざまなサブクラスと親クラスのコードは一緒に保存されません。

アクセスのルールでは、サブクラスのコードが、親クラスまたは祖先クラスにプライベートなインスタンス変数に割り当てられたメモリにアクセスすることはできません。

ただし、この場合、これほど詳細に検討する価値はほとんどありません。それが私の経験です。他の人はそれを異なって見るかもしれません。

注:リフレクションを介してプライベート変数にアクセスする方法があります。

可視性

私は記憶から仕事をしているので、ここで助けが必要かもしれません。

メンバー変数に割り当てられた可視性には4つのレベルがあります。これらは、クラス変数とメソッドで使用されるものと同じ4つです。

private-これらの変数には、宣言されているのと同じクラス内のコードからのみアクセスできます。(まあ...それらはそのクラス内の内部クラスからもアクセスできます。)

パッケージ-これらには、同じクラス内のコードと、そのクラスと同じパッケージ内の任意のクラスのコードからアクセスできます。そのコードを含むクラスは、ソースファイルまたはjarファイル、あるいは実際にはクラスパスのどこにでも存在する可能性があります。(注:キーワード「package」はありません。可視性を示す他のキーワードがない場合、変数にはパッケージレベルの可視性があります。「package」という単語を/ * * /コメントに入れたいと思います。)

保護-これらには、同じクラス内のコード、そのクラスの任意のサブクラスのコード、およびそのクラスと同じパッケージの任意のクラスのコードからアクセスできます。

public-これらは、他のクラス内のコードからアクセスできます。

警告:他の方法では表示されると予想されるコードが表示されない方法もあります。これは、ClassLoaderの動作方法が原因です。Java EEにはクラスローダーのネストがあり、あるクラスローダーによってロードされたコードが別のクラスローダーによってロードされたコードから見えなくなる可能性があります。最終的に同じフルネーム(パッケージを含む)の2つのクラスになる可能性があります。私はこれをすべて「高度な」トピックと考えており、それを説明するためにそれを読む必要があります。私はそれが起こり、あなたに可視性について疑問を抱かせる可能性があることに注意したかったのです。

public class MyClass {
    private int foo1 = 1;       // visible in this class only
    protected int foo2 = 2;     // visible here, in subclasses and in classes with same package
    int foo3 = 3;               // visible here and in classes with the same package
    public int foo4 = 4;        // visible here, there and everywhere

    /* package */ int foo5 = 5; // how I like to do 'package' variables with a comment
                                //  to show I intended to do it on purpose. If you read
                                //  my code you don't have to wonder if I forgot it.

    ...
}

最後の実用的な注意事項:長期的には、ほとんどすべてのメンバー変数をプライベートにすることは非常に便利です。それらをより見やすいものに変更する必要がある場合は、そうするか、目的の可視性を持つgetterメソッドとsetterメソッドを作成するだけです。1つの利点は、ゲッターを提供し、セッターを提供しない場合、またはゲッターがパブリックでセッターが保護されている場合に、読み取り専用アクセスを許可できることです。設定はできるが読み取りはできない書き込み専用変数を作成することもできます。これは依存性注入で機能しますが、それについてコメントを入れる必要があります。多分あなたは利点を見ることができます。欠点は、より多くのコード行を記述できることですが、他のIDEの中での日食は、必要に応じてそれらのメソッドを生成します。

于 2013-01-25T20:35:47.117 に答える
7

サブクラスのインスタンスには、そのスーパークラスのすべてのメンバーが含まれていますが、サブクラス内からプライベートメンバーにアクセスすることはできません。

于 2013-01-25T20:32:29.173 に答える