web-dev-qa-db-ja.com

セッターメソッドを使用してプロパティ値を変更できる場合、カプセル化はどのように使用されますか?

私は何度も理解しようとしましたが、理解できませんでした。

カプセル化は、クラスのフィールドをプライベートにして、パブリックメソッドを介してフィールドへのアクセスを提供する手法です。フィールドがプライベートとして宣言されている場合、クラス外のユーザーはそのフィールドにアクセスできないため、クラス内のフィールドは非表示になります。

セッターメソッドを使用してフィールドの値を変更するにはどうすればよいですか?フィールドに直接アクセスできないようにするにはどうすればよいですか?カプセル化の実際の用途は何ですか?

19
PSR

ageプロパティがあるとします。

ユーザーは-10の値を入力できます。これは有効な数値ですが、無効な年齢です。セッターメソッドは、そのようなものをキャッチできるようにするロジックを持つことができます。

もう1つのシナリオは、ageフィールドがあるが、それを非表示にすることです。 Date of Birthフィールドを設定することもでき、そのセッターでは次のようになります。

...
private int age
private Date dob

...
public void setDateOfBirth(Date dob)
{
    this.dob = dob;
    age = ... //some logic to calculate the age from the Date of Birth.
}
26
npinti

私もあなたと同じように長い間混乱してきました。私は「オブジェクト指向プログラミング言語でのカプセル化と継承」の本と、カプセル化の重要性を説明したウェブサイトを読むまで、私は混乱しています。私は実際にウェブサイトから本に導かれました。

カプセル化は「情報の隠蔽」であると常に言われているため、カプセル化はセキュリティを主な用途として焦点を合わせているのかもしれません。はい、あなたは実際に情報を隠していますが、それは人々を混乱させる可能性があるので、それは定義ではありません。

カプセル化は、「厳密な外部インターフェースを定義することにより、個別に作成されたモジュール間の相互依存関係を最小限に抑える」(本から引用)だけです。つまり、モジュールを構築しているときに、クライアントと私の間に、クライアントがモジュールにアクセスする方法についての厳密な契約が必要です。その理由は、クライアント、ライフ、アプリケーション、または私のモジュールを使用しているものに影響を与えることなく、内部の仕組みを改善できるようにするためです。それらの「モジュール」は、私のモジュールの内部動作に正確に依存するのではなく、「外部インターフェース」に依存するため、私はそれらを利用できるようにしました。

クライアントにセッターを提供せず、変数に直接アクセスできるようにした場合、クライアントが変数を使用する前に、変数にいくつかの制限を設定する必要があることに気づきました。私のクライアントの人生、または巨大な費用を伴う私のクライアントのアプリケーション。しかし、「厳格な外部インターフェース」、つまりセッターを作成して「厳格な契約」を提供した場合、クライアントにほとんどまたはまったく費用をかけずに、内部の仕組みを簡単に変更できます。

(カプセル化を使用して)セッターの状況で、変数を設定したときに、変数が割り当てられたことを通知するメッセージが返された場合、「インターフェイス」を介してメッセージを送信し、クライアントに新しいことを通知できます。私のモジュールが相互作用しなければならない方法、すなわち「あなたは負の数を割り当てることができない」それは私のクライアントが負の数を割り当てようとする場合です。しかし、カプセル化を使用せず、クライアントに変数への直接アクセスを許可して変更を加えた場合、システムがクラッシュする可能性があります。これは、実装した制限では、ネガティブとクライアントを保存できないためです。常にネガを保存できたので、私のクライアントはクラッシュしたシステムを手にします(その「クラッシュしたシステム」が銀行システムだった場合、何が起こるか想像してみてください)。

したがって、カプセル化はモジュール間の依存関係を減らすことに関するものなので、セキュリティよりも、対話する他のモジュールにほとんどまたはまったく費用をかけずに、改善を「静かに」行うことができます。相互作用するモジュールは「厳密な外部インターフェースまたは厳密な規約」に依存しているためです。

私はこれがそれを適切に説明することを望みます。そうでない場合は、以下のリンクにアクセスして自分で読んでください。

カプセル化が重要

オブジェクト指向プログラミング言語でのカプセル化と継承

17
Uche Dim

カプセル化の実際の用途は、値の設定方法で追加のチェック/処理を実行できるという事実にもあります。

11
Eugene

フィールドへのアクセスを厳密に禁止するのではなく、他のユーザーが特定のフィールドにアクセスする方法を制御します。たとえば、セッターメソッドに検証を追加したり、フィールドのセッターメソッドが呼び出されたときに他の依存フィールドを更新したりできます。

フィールドへの書き込みまたは読み取りアクセスを防ぐことができます(たとえば、それぞれゲッターまたはセッターのみを提供することにより)。ただし、プロパティを使用してカプセル化すると、それ以上のことが可能になります。

5
mikey

セッターメソッドを使用してフィールドの値を変更する方法。

Setterメソッドでそれができる場合のみ。

フィールドへのアクセスをどのように防止していますか?

セッターとゲッターは、フィールドにアクセスできるかどうか、またどのようにアクセスできるかを制御します。

セッターは、値が有効かどうかをチェックする場合があります。これを許可するかどうかをSecurityManagerに尋ねる場合があります。データ型間で変換する場合があります。等々。

3
Thilo

プライベートフィールドがある場合、クラスの外にはアクセスできません。つまり、基本的にこれらのフィールドは外界には存在せず、はい、セッターメソッドを介して値を変更できますが、セッターメソッドを使用すると、より柔軟な制御が可能になります。誰がフィールドを変更し、どの値に変更できるか...基本的にはカプセル化により、フィールドを変更する方法とユーザーに制限を課します。たとえば、次のようにします:プライベートダブル給与、セッターメソッドでは、次のように記述できる給与フィールドをhrスタッフだけが変更できるように制限できます。

void setSalary(Person p,double newSalary)    
{    
//only HR objects have access to change salary field.   
If(p instanceof HR && newSalary>=0)    
//change salary.   
else   
 S.o.p("access denied");    
} 

給与が公開されていて、直接アクセスできる場合、それを変更できると想像してください。ただし、必要なときにいつでも、これは基本的にカプセル化の重要性です。

3
Sello

カプセル化の背後にある主なアイデアは、データの非表示です。オブジェクト指向プログラミングでカプセル化を使用する理由はいくつかあります。カプセル化の理由として特定された理由のいくつかは次のとおりです(カプセル化の実際の使用法)。

  1. 保守性の向上:すべてのプロパティがプライベートでカプセル化されている場合、メソッドを変更するだけでプログラムを保守するのは簡単です。

  2. Make Debugging Easy:これは上記の点と一致しています。オブジェクトはメソッドを介してのみ操作できることを知っています。したがって、これによりバグのデバッグとキャッチが容易になります。

  3. 制御された環境を持っている:ユーザーがオブジェクトを介して、指定されたオブジェクトを制御された方法で使用できるようにします。

  4. Hide Complexities:ユーザーに関係のない複雑度を非表示にします。場合によっては、一部のプロパティとメソッドは内部でのみ使用され、ユーザーはこれらについて知る必要はありません。これにより、ユーザーはオブジェクトを簡単に使用できます。

したがって、「セッターメソッドを使用してプロパティ値を変更できる場合のカプセル化の使用法は何ですか?」という質問に答えるために、いくつかの主な理由がありますカプセル化を使用する理由。 理由を理解するために、ゲッターとセッターは便利です。これは article から得られるいくつかの重要なポイントです。

  • フィールドに保存できる値を制限できます(つまり、性別はFまたはMでなければなりません)。

  • フィールドが変更されたときにアクションを実行できます(トリガーイベント、検証など)。

  • メソッドを同期することでスレッドセーフを提供できます。

  • 新しいデータ表現(つまり、計算フィールド、異なるデータタイプ)に切り替えることができます

2

Encapsultaionは、メンバーを非公開にし、ゲッターメソッドとセッターメソッドでそのメンバー変数にアクセスすることにより、メンバー変数を非表示にするために使用されます。

カプセル化クラス{

private int value ;

Encapsulation() {
    System.out.println("constructor calling ");
}

void setValue(int value){
    this.value = value;
}
int getValue() {
    return value;
}

}クラスEncapsulationMain {

public static void main(String args[]) {
    Encapsulation obj = new Encapsulation();
    obj.setValue(4);
    //System.out.print("value is "+obj.value); 
    //obj.value = 55;
    //System.out.print("obj changing the value"+obj.value);
    System.out.print("calling the value through the getterMethod"+obj.getValue());
}

}

クラス外のプライベート値にはアクセスできません。

1
Saurabh Mishra

次のセッター/ゲッターを使用してカスタムDateクラスを作成するとします。

getDay() 
getMonth() 
getYear() 
setDay() 
setMonth() 
setYear()

内部的には、以下を使用して日付を格納できます。

private int day;
private int month;
private int year;

または、Java.lang.Date-objectを使用して日付を保存することもできます。

private Date date;

カプセル化は、クラスが内部でどのように機能しているかを公開しません。クラスの動作を変更するための自由度が増します。クラスへのアクセスを制御するオプションを提供します。ユーザーが入力した内容が有効かどうかを確認できます(ユーザーに32の値で1日を入力させたくない)。

1
MMeersseman

その目的は、変化しやすいものを保護することに他なりません。あなたはウェブ上にたくさんの例を持っているので、私はそれのいくつかの利点をあなたに与えます:

  1. カプセル化されたコードはより多く柔軟であり、新しい要件に合わせて簡単に変更できます
  2. 誰が何にアクセスできるかを制御できます。 (!!!)
  3. 書くのに役立ちますimmutable class Javaで
  4. コードの他の部分に影響を与えることなく、コードの一部を変更できます。
1
aran

メソッドを介してフィールドにアクセスすると、OOPになるため、違いがあります。たとえば、クラスを拡張して、直接アクセスでは実行できない動作を変更できます。ゲッター/セッターがある場合、クラスのプロキシを作成し、AOPを実行するか、1.4の動的プロキシを作成できます。あなたはあなたのクラスからモックを作り、ユニットテストをすることができます...

1

カプセル化とは、データを非表示にすることだけではありません。それはすべて、フィールドに格納されているものを制御することです。カプセル化を使用して、要件に応じてフィールドを読み取り専用または書き込み専用にできます。また、ユーザーはフィールドにデータがどのように格納されるかを知りません。セッターメソッドで特別な暗号化を使用して、フィールドに格納できます。たとえば、人間はオブジェクトです。人間の名前フィールドのみをユーザーに読み取らせ、修正は不要です。次に、名前フィールドでgetメソッドのみを定義します。これは、カプセル化が役立つ方法です。

クラスがある場合、そのプロパティはすべてプライベートです。つまり、クラスの外部からアクセスすることはできません。クラスのプロパティを操作する唯一の方法は、そのパブリックメソッドを使用することです。

これらのメソッド(セッター)へのパブリックアクセスを許可することにより、値を変更しています。

カプセル化を使用して、クラスのフィールドを作成できますread-onlyまたはwrite-only.

0
Suresh Atta

カプセル化を使用することで、クラスを外界(他のクラス)から分離し、外界はアクセス修飾子を使用してクラスインスタンス変数にアクセスおよび変更できます。これにはいくつかの利点があります。

-ゲッター/セッターメソッドでログを記録できます。

-/ normalizeを検証できます(スペースのトリム、特殊文字の削除など)。setterメソッドでの入力。

また、実装を外部から隠すことができます。たとえば、クラスに配列リストのようなコレクションがあり、次のようにゲッターメソッドを記述します。

public List<t> get collection(){
 return new  ArrayList<t>(this.arrayList);
}

したがって、この場合、将来、コレクションの実装を配列リストからリンクリストのようなものに変更することを決定した場合、外の世界は実装について何も知らないため、自由に変更できます。

0
Mr.Q

全員に変数に直接アクセスさせる代わりに:

public Object object;

SETおよびGETメソッドを使用するか、またはGETメソッドのみを使用することをお勧めします(その変数に他の値を設定したくない場合もあります)。

public Object getObject() { 

return object;
}

public void setObject(Object object) { 

this.object = object;
}
0
user2245180