class Person
{
private BankAccount account;
Person(BankAccount account)
{
this.account = account;
}
public Person someMethod(Person person)
{
//Why accessing private field is possible?
BankAccount a = person.account;
}
}
デザインを忘れてください。 OOPはプライベートオブジェクトがクラスに対してプライベートであることを指定します。私の質問は、なぜOOPプライベートフィールドがクラスレベルのアクセス権を持つように設計され、 オブジェクトレベルアクセスではない?
私も答えに少し興味があります。
私が見つけた最も満足のいく答えは、別の投稿のArtemixからです(AClassをPersonクラスに名前変更しています): なぜオブジェクトレベルではなくクラスレベルのアクセス修飾子がありますか?
Private修飾子は、カプセル化の原則を強制します。
Personの実装は時間とともに変化する可能性があるため、「外部世界」はPersonの内部プロセスを変更すべきではないという考えです(実装の違いを修正するには、外部世界全体を変更する必要があります-これはほぼ不可能です)。
Personのインスタンスが他のPersonインスタンスの内部にアクセスする場合-両方のインスタンスがPersonの実装の詳細を常に知っていることを確認できます。 Personプロセスの内部のロジックが変更された場合-しなければならないことは、Personのコードを変更することだけです。
編集:くださいvoteArtemixの答え。ただコピー&ペーストしています。
Java言語仕様、セクション6.6.1。アクセシビリティの決定 を参照してください
それは述べています
それ以外の場合、メンバーまたはコンストラクターが
private
と宣言されている場合、メンバーまたはコンストラクターの宣言を囲む最上位クラス(7.6)の本体内で発生する場合にのみアクセスが許可されます。
詳細については、上のリンクをクリックしてください。だから答えは:James Goslingと他のJavaの著者がそのように決めたからです。
良い質問。オブジェクトレベルのアクセス修飾子は、カプセル化の原則をさらに強化するようです。
しかし、実際には逆です。例を見てみましょう。オブジェクトのプライベートメンバーにアクセスできない場合、コンストラクターでオブジェクトをディープコピーするとします。次に、唯一の可能な方法は、すべてのプライベートメンバーにパブリックアクセサーを追加することです。これにより、オブジェクトはnakedシステムの他のすべての部分になります。
したがって、カプセル化とは、世界中のすべての地域に閉じられているという意味ではありません。それはあなたが誰に開かれたいかを選択することを意味します。
これは、あなたがclass Person
-クラスは、それ自身のタイプのクラス内で突くことができます。これは、たとえば次のようなコピーコンストラクタを作成する場合に非常に役立ちます。
class A
{
private:
int x;
int y;
public:
A(int a, int b) x(a), y(b) {}
A(A a) { x = a.x; y = y.x; }
};
または、operator+
およびoperator-
多数のクラスの場合。
Javaのプライベート可視性のセマンティクスがオブジェクトレベルではなくクラスレベルである理由についての質問に対する私の2セント。
ここでは、コンビニエンスが重要なようです。実際、オブジェクトレベルでのプライベートな可視性は、OPで示されているシナリオでは、メソッドを他のクラス(たとえば、同じパッケージ内)に公開することを強制していました。
実際には、オブジェクトプライベートレベルでの可視性と比較した場合、クラスプライベートレベルでの可視性(Javaで提供されるような)が問題を引き起こすことを示す例も見つけることもできませんでした。
とはいえ、可視性ポリシーのよりきめ細かいシステムを備えたプログラミング言語は、オブジェクトレベルとクラスレベルの両方でオブジェクトの可視性を確保できます。
たとえば、 Eiffel は選択的エクスポートを提供します。{NONE}(オブジェクトプライベート)から{ANY}(publicと同等)に任意のクラス機能を任意のクラスにエクスポートできます。デフォルト)、{PERSON}(クラスプライベート、OPの例を参照)、クラスの特定のグループ{PERSON、BANK}に。
また、エッフェルでは、属性をプライベートにし、他のクラスが属性を割り当てないようにするためのゲッターを作成する必要がないことにも注目してください。 Eiffelのパブリック属性はデフォルトで読み取り専用モードでアクセスできるため、値を返すためだけにゲッターは必要ありません。
もちろん、属性を設定するにはまだセッターが必要ですが、その属性の「割り当て者」として定義することで非表示にできます。これにより、必要に応じて、セッター呼び出しの代わりに、より便利な割り当て演算子を使用できます。
ここで最初に理解しなければならないことは、OOPの原則に従う必要があることです。したがって、カプセル化はパッケージ内のデータをラップし(つまりクラス)、すべてのデータをObjectとして表現し、アクセスしやすいそのため、フィールドを個別にアクセスするよりも非プライベートとして作成した場合。そして、それは悪いパラチスになります。
private
access modifierは、class内でのみ表示されるためです。このメソッドはまだクラスにありますです。
Javaでリフレクションの概念を使用すると、フィールドとメソッドのプライベートを変更できます
private
フィールドは、フィールドが宣言されているクラス/オブジェクトでアクセス可能です。配置されているクラス/オブジェクト以外の他のクラス/オブジェクトに対してプライベートです。