JavaRush /Java Blog /Random-JA /ゲッターとセッター

ゲッターとセッター

Random-JA グループに公開済み
こんにちは!これまでの講義で、フィールドとメソッドを使用して独自の本格的なクラスを作成する方法をすでに学びました。これは重大な進歩です、よくやった!しかし今、不愉快な真実を言わなければなりません。クラスを正しく作成できませんでした。なぜ?一見したところ、このクラスにはエラーはありません。
public class Cat {

   public String name;
   public int age;
   public int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}
実際、あります。仕事に座っているときに、猫を表す次のようなクラスを作成したと想像してくださいCat。そして彼は家に帰りました。あなたがいない間、別のプログラマが出勤して独自のクラスを作成しMain、そこであなたが書いたクラスを使い始めましたCat
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
なぜそれをしたのか、どのように起こったのかは関係ありません。おそらくその人は疲れていたか、十分な睡眠をとっていなかったのでしょう。もう 1 つ重要なことは、現在のクラスではCatフィールドにクレイジーな値を割り当てることができるということです。その結果、プログラムには、この猫の年齢が -1000 歳であるなど、誤った状態のオブジェクトが含まれています。結局私たちはどんな間違いを犯したのでしょうか? クラスを作成したときに、そのデータを公開しました。 フィールドnameageおよびweightフィールドはパブリック ドメインです。これらはプログラム内のどこからでもアクセスできます。オブジェクトを作成するだけで、すべてのプログラマが「 」 演算子Catを介してそのデータに直接アクセスできるようになります。.
Cat cat = new Cat();
cat.name = "";
ここでは、フィールドに直接アクセスしてname、その値を設定します。 不正な外部干渉から何らかの方法でデータを保護する必要があります。 そのためには何が必要なのでしょうか?まず、すべてのインスタンス変数 (フィールド) を修飾子でマークする必要がありますprivate。Private は Java で最も厳密なアクセス修飾子です。これを使用すると、そのクラスのCat外部からはクラスのフィールドにアクセスできなくなります。
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }
}

public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";//error! The name field in the Cat class has private access!
   }
}
コンパイラはこれを認識し、すぐにエラーを生成します。現在、畑は保護されているようです。しかし、猫へのアクセスは「厳重に」閉鎖されていることが判明しました。プログラムは、必要な場合でも既存の猫の体重を取得することさえできません。これもオプションではありません。この形式では、クラスを使用することは事実上不可能です。理想的には、データへの何らかの制限されたアクセスを許可する必要があります。
  • 他のプログラマーもオブジェクトを作成できるはずですCat
  • 既存のオブジェクトからデータを読み取ることができる必要があります (たとえば、既存の猫の名前や年齢を取得する)
  • フィールド値を割り当てることもできるはずです。しかし同時に、正しい値だけが必要です。私たちのオブジェクトは誤ったものから保護されなければなりません (「年齢 = -1000 年」などは禁止)。
要件のリストはまともです!しかし実際には、これらすべては特別なメソッドであるgettersetter を使用して簡単に実現できます。
ゲッターとセッター - 2
この名前は、英語の「get」-「receive」(つまり、「フィールドの値を取得するメソッド」)とset -「set」(つまり、「フィールドの値を設定するメソッド」)に由来しています。私たちのクラスを例として使用して、それらがどのように見えるかを見てみましょうCat:
public class Cat {

   private String name;
   private int age;
   private int weight;

   public Cat(String name, int age, int weight) {
       this.name = name;
       this.age = age;
       this.weight = weight;
   }

   public Cat() {
   }

   public void sayMeow() {
       System.out.println("Meow!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

   public int getWeight() {
       return weight;
   }

   public void setWeight(int weight) {
       this.weight = weight;
   }
}
ご覧のとおり、すべては非常に単純です :) ほとんどの場合、それらの名前は、get/set という単語+ それらが担当するフィールドの名前で構成されます。たとえば、メソッドは呼び出されたオブジェクトのgetWeight()フィールド値を返します。weightプログラムでは次のようになります。
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       String barsikName = barsik.getName();
       int barsikAge = barsik.getAge();
       int barsikWeight = barsik.getWeight();

       System.out.println("Cat name: " + barsikName);
       System.out.println("Cat's age: " + barsikAge);
       System.out.println("Weight of the cat: " + barsikWeight);
   }
}
コンソール出力:

Name кота: Барсик
Возраст кота: 5
Вес кота: 4
別のクラス ( Main) からフィールドにアクセスできるようになりますCatが、ゲッターを介してのみアクセスできます。ゲッターにはアクセス修飾子があることに注意してくださいpublic。これは、ゲッターがプログラム内のどこからでもアクセスできることを意味します。値を割り当てる場合はどうすればよいでしょうか? Setterメソッドがこれを担当します
public void setName(String name) {
   this.name = name;
}
ご覧のとおり、彼らの仕事も単純です。setName()オブジェクトのメソッドを呼び出しCat、引数として文字列を渡します。この文字列はnameオブジェクトのフィールドに割り当てられます。
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);

       System.out.println("The original name of the cat is " + barsik.getName());
       barsik.setName("Basil");
       System.out.println("The new name of the cat -" + barsik.getName());
   }
}
ここではゲッターとセッターの両方を使用しました。まず、ゲッターを使用して、猫の初期名を受信して​​コンソールに出力しました。次に、セッターを使用して、nameそのフィールドに新しい値「Vasily」が割り当てられました。次に、ゲッターを使用して名前を再度取得し、本当に変更されたかどうかを確認しました。コンソール出力:

Изначальное Name кота — Барсик
Новое Name кота — Васorй
違いは何でしょうか?セッターがある場合でも、オブジェクト フィールドに誤った値を割り当てることもできます。
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
コンソール出力:

Возраст Барсика — -1000 лет
違いは、セッターが本格的なメソッドであることです。また、フィールドとは異なり、メソッドでは、受け入れられない値を防ぐために必要な検証ロジックを配置できます。たとえば、年齢として負の数値を割り当てることを簡単に無効にすることができます。
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age cannot be negative!");
   }
}
これで、コードが正しく動作するようになりました。
public class Main {

   public static void main(String[] args) {

       Cat barsik = new Cat("Barsik", 5, 4);
       barsik.setAge(-1000);

       System.out.println("Age of Barsik -" + barsik.getAge() + " years");
   }
}
コンソール出力:

Ошибка! Возраст не может быть отрицательным числом!
Возраст Барсика — 5 лет
セッター内には制限があり、誤ったデータを設定しようとする試みから保護されます。バルシクの年齢は変わらなかった。 ゲッターとセッターは常に作成する必要があります。フィールドに取り得る値に制限がない場合でも、それによる害はありません。状況を想像してください。あなたと同僚が一緒にプログラムを書いています。パブリック フィールドを含むクラスを作成するCatと、すべてのプログラマがそれらを必要に応じて使用します。そして、ある晴れた日、あなたは次のように気づきましたweight。セッターを作成して、すべてのフィールドをプライベートにする必要があります。」あなたがコードを作成すると、同僚が書いたすべてのコードが即座に壊れてしまいます。結局のところ、彼らはフィールドに直接アクセスするコードをすでに大量に書いていたのですCat
cat.name = "Hippopotamus";
そして今、フィールドはプライベートになり、コンパイラは大量のエラーを生成します。
cat.name = "Hippopotamus";//error! The name field of the Cat class has private access!
このような状況では、フィールドを非表示にして、最初から ゲッターセッターを作成する方が良いでしょう。同僚全員がそれらを使用し、フィールド値を制限する必要があることに後で気づいた場合は、セッター内にチェックを追加するだけです。そして、すでに書かれたコードを壊す人は誰もいません。もちろん、特定のフィールドへの読み取り専用アクセスが必要な場合は、そのフィールドに対してゲッターを 1 つ作成できます。 「外部」、つまりクラスの外部では、メソッドのみがアクセス可能である必要があります。データは隠蔽する必要があります。
ゲッターとセッター - 4
携帯電話でも例えることができます。電源が入った通常の携帯電話の代わりに、すべての配線や回路などが入っているオープンケースの電話が与えられたと想像してください。突き出した。電話は機能します。頑張って図をいじれば、電話をかけることもできるかもしれません。しかし、おそらくあなたはそれを壊すでしょう。代わりに、製造会社はインターフェイスを提供します。顧客は必要な番号をダイヤルし、受話器で緑色のボタンを押すだけで通話が始まります。そして彼は、回路や配線の内部で何が起こっているのか、それらがどのようにその役割を果たしているのかなど気にしません。この例では、会社は電話の「内部」(データ) へのアクセスを制限し、インターフェイス (メソッド) のみを外部に残しています。その結果、クライアントは望んでいたもの (電話をかけること) を得ることができ、内部では何も壊れることはありません。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION