17

私の質問には、具体的には Java、抽象クラス、および保護されたデータの使用が含まれます。すべてのデータを非公開にし、保護されたゲッター/セッターのみを使用する必要があると言われています。

ここで、クラスのカジュアルなユーザーによる直接操作からデータを保護したいこと、およびパブリック データ メンバーは一般的に疑わしい慣行であることを理解しています。「Java プロテクト フィールド vs パブリック ゲッター」( Java プロテクト フィールド vs パブリック ゲッター) を見てきましたが、まだ疑問があります。

protected int i;  

抽象クラスでは以下よりも悪い:

private int i;  
protected int geti();  
protected void seti(int j); 

子クラスに親/共通機能を提供するために抽象クラスが正確に存在し、保護されたスコープが子へのアクセスを提供することを意図している場合、私はマイナス面を見ていませんユーザーからデータを保護します。上記の質問で、ほとんどの回答は、一般にデータを公開ではなく非公開にする理由の問題に対処しているように見えることに注意してください。私は、子供が使用することを意図した抽象的な親に存在するデータに特に質問を集中しようとしています。これまでに聞いた唯一の合理的なコメントは、親で保護されたデータ (上記の int i など) を使用すると、子クラスで宣言されていない変数を参照するコードが子クラスに残るということです。あまり説得力のない引数です (基本クラスの共通保護データ メンバーを参照してください。) いつかアクセスを変更したくなるかもしれませんが、今度はインターフェースを尊重する必要があります。これは抽象クラスであり、常に 100% 拡張されることを意図しています。

ありがとう!本への特定のタイトル/ページ番号の参照は、「..基本的なJavaプログラミングテキスト...」への参照よりもはるかに役立ちます。

========================================= 10-13-2010
これは、保護されたデータに関する質問と同じくらい、抽象クラスに関する質問でした。OOP でデータを隠すことが良いことかどうかについての回答で、焦点がずれているように見えるのは残念です (回答: はい)。ここには、抽象クラスの性質、通常の非最終クラスとの違い、抽象親で使用するデータ項目の名前と型を固定することの利点など、多くの深みがあります。子クラス。ここには、革新と、抽象的な親クラスから子クラスの実装にまで拡張されたより大きな制御の可能性があると思います。私は、データ隠蔽の利点などの一般原則がドグマになり、イノベーションや新しいパターンやアイデアの開発を阻害する可能性があることを懸念しています。

貢献してくれたすべての人に感謝します。

4

8 に答える 8

11

フィールドがプライベートで、アクセスがゲッターとセッターを介して行われる場合、ゲッターとセッターを再実装することができます (たとえば、フィールドをドロップして、外部ソースから値を更新/読み取る)。したがって、「フィールド」の動作を変更できます。子クラスに触れずに。

これが価値があるかどうかは、あなた次第です。

于 2010-08-19T20:09:31.153 に答える
9

保護されたメソッドは、パブリック メソッドが他のすべてのインターフェイスと同じように、サブクラスのインターフェイスと考えてください。

アクセサーを提供すると、基本クラスはその状態を維持できます。意図的なトリックなしに、サブクラスがそれを破損することはありません。

于 2010-08-19T20:12:05.000 に答える
3

アクセスが少ないことは欠点ではなく、利点です。クラスは常に、可能な限り多くの内部状態へのアクセスを制限する必要があります。なぜ内部を隠す必要があるのか​​ 考えるのではなく、なぜそれらを公開する必要があるのか​​ を考えてください。この場合、すべての場合と同様に、変数を公開する本当に正当な理由がない限り、公開しないでください。

于 2010-08-19T23:45:13.447 に答える
1

Java では、保護されたメンバーは、拡張クラスに加えて、同じパッケージ内のすべてのメンバーにアクセスできます。フィールドをプライベートにすると、同じパッケージ内のクラスが直接アクセスできなくなります。

同様に、アレックスが以前に提起した点もあります。

于 2010-08-19T20:16:09.767 に答える
1

お子様が直接アクセスする必要がない場合、なぜ許可するのでしょうか?

protected を使用することはマイナス面ではありません。しかし、それが必要でない場合は、それを避けてフィールドへのアクセスを制御する方がよいでしょう。

于 2010-08-19T20:12:05.647 に答える
0

使用するとフィールドのオーバーライドが可能になるため、ゲッター/セッターを使用する必要がprotected int i;あります(これは絶対に避けたい)。

メソッドのオーバーライドとは動作が異なるため、フィールドのオーバーライドを禁止する必要があります。フィールドのオーバーライドによって、オーバーライドされたフィールドにアクセスできなくなることはありません(参照のタイプによって、操作しているフィールドのインスタンスが決まります)。

アクセス可能なフィールドは、finalであるか、finalのクラスである必要があります。

public class OverridingFun {
    public static class Base {
        public int i = 1;
        public int getI(){ return i; }
    }
    public static class A extends Base {
        public int i = 2;
        public int getI(){ return i; }
    }
    public static class B extends A {
        public int i = 3;
        public int getI(){ return i; }
    }
    public static void main(String [] args){
        B b = new B();
        A bAsA = b;
        Base bAsBase = b;

        System.out.println(b.getI());//3
        System.out.println(bAsA.getI());//3
        System.out.println(bAsBase.getI());//3

        System.out.println(b.i);//3
        System.out.println(bAsA.i);//2
        System.out.println(bAsBase.i);//1

        b.i = 4;
        bAsA.i = 5;
        bAsBase.i = 6;

        System.out.println(b.i);//4
        System.out.println(bAsA.i);//5
        System.out.println(bAsBase.i);//6
    }
}

一見すると、これはコードを読みにくくするようなもののように見えますが、機能に影響を及ぼします。セッターが使用されていないため、フィールドが派生クラスによってオーバーライドされるとすると、ベースフィールドを自動的に更新する方法も、誰かがベースフィールドを変更したかどうかを検出する方法もありません(ベース値はまだアクセス可能であるため)。派生フィールドを更新します。基本状態と派生状態が同期しなくなる可能性があり、エラーを追跡するのが難しいことは容易に想像できます。簡単に言えば、非常に脆弱なAPIになります。

残念ながら、これを防ぐ方法はありませんfinal。これは、オーバーライドから保護するキーワードによって、フィールドが1回だけ書き込まれるためです。したがって、書き込み可能でオーバーロードできないフィールドはありません。

個人的には、言語設計者がフィールドのオーバーライドを許可したことにかなり驚いています。セッターを使用する利点は、各レベルがそれ自体の状態の整合性を保証し、派生クラスがそれを汚していないことを信頼できることです。フィールドのオーバーライドは、問題を引き起こしているだけです。

于 2012-04-08T01:44:43.217 に答える
0

誰かがあなたのクラスをサブクラス化し、サブクラスを現在のクラスと同じパッケージに入れる場合、彼らはあなたのゲッターとセッターをオーバーライドしたいと思うかもしれません。たとえば、 をi1 より大きい値にのみ設定できるようにしたいと考えています。

それ以外は、本当にあなた次第です。ただし、慣例では、すべてのゲッターとセッターがあります。

于 2010-08-19T20:14:53.420 に答える
0

継承によって関連付けられたクラス間であっても、情報の隠蔽は価値があります。

上記のalexが指摘したように、再実装を許可することに加えて:

  • メソッドにブレークポイントを設定できます。
  • 制約を 1 か所に追加できます。
于 2010-08-19T20:32:51.423 に答える