CodeGym /Java Blog /ランダム /ゲッターとセッター
John Squirrels
レベル 41
San Francisco

ゲッターとセッター

ランダム グループに公開済み
こんにちは!前のセクションでは、メソッドとフィールドを使用して独自の本格的なクラスを宣言する方法をすでに学習しました。今日のレッスンでは、Java のゲッターとセッターについて説明します。これは重大な進歩です、よくやった!しかし今、不愉快な真実を言わなければなりません。クラスを正しく宣言しませんでした。なぜ?一見すると、次のクラスには間違いがありません。

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;
   }
}
彼がなぜそれをしたのか、そしてそれがどのように起こったのかは関係ありません(おそらくその男は疲れていたか、十分な睡眠をとっていなかったでしょう)。他に重要なのは、現在のCatクラスでは、フィールドにまったく非常識な値を割り当てることができます。その結果、プログラムには無効な状態のオブジェクトが含まれます (たとえば、この猫の年齢は -1000 歳です)。では、クラスを宣言するときにどのような間違いがあったのでしょうか? 私たちはクラスのデータを暴露しました。名前、年齢、体重のフィールドは公開されます。これらはプログラム内のどこからでもアクセスできます。Catオブジェクトを作成するだけで、プログラマはドット ( . ) 演算子 を介してそのデータに直接アクセスできます。

Cat cat = new Cat();
cat.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 Cat class's name field is private!
   }
}
コンパイラはこれを認識し、すぐにエラーを生成します。これで、フィールドはある程度保護されました。しかし、おそらくアクセスを厳重に遮断しすぎたことが判明しました。必要な場合でも、プログラム内で既存の猫の体重を取得することはできません。これもオプションではありません。現状では、私たちのクラスは基本的に使用できません。理想的には、ある種の制限されたアクセスを許可する必要があります。
  • 他のプログラマはCatオブジェクトを作成できるはずです
  • 既存のオブジェクトからデータを読み取ることができる必要があります (たとえば、既存の猫の名前や年齢を取得する)
  • フィールド値を割り当てることもできるはずです。ただし、その際には、有効な値のみを許可する必要があります。オブジェクトは無効な値 (例: age = -1000 など) から保護される必要があります。
これは適切な要件のリストです。実際には、これらすべてはゲッターとセッターと呼ばれる特別なメソッドを使用して簡単に実現できます。
ゲッターとセッター - 2
これらの名前は、「get」 (つまり、「フィールドの値を取得するメソッド」) と「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()メソッドは、呼び出されたオブジェクトの重みフィールドの値を返します。プログラムでは次のようになります。

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       String smudgeName = smudge.getName();
       int smudgeAge = smudge.getAge();
       int smudgeWeight = smudge.getWeight();

       System.out.println("Cat's name: " + smudgeName);
       System.out.println("Cat's age: " + smudgeAge);
       System.out.println("Cat's weight: " + smudgeWeight);
   }
}
コンソール出力:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
これで、別のクラス ( Main )がCatフィールドにアクセスできるようになりますが、ゲッターを介してのみアクセスできます。ゲッターには public アクセス修飾子があることに注意してください。つまり、ゲッターはプログラム内のどこからでも利用できます。しかし、値を割り当てる場合はどうでしょうか? これがセッターメソッドの目的です

public void setName(String name) {
   this.name = name;
}
ご覧のとおり、これらもシンプルです。CatオブジェクトでsetName()メソッドを呼び出し、文字列を引数として渡すと、その文字列がオブジェクトの名前フィールドに割り当てられます。

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);

       System.out.println("Cat's original name: " + smudge.getName());
       smudge.setName("Mr. Smudge");
       System.out.println("Cat's new name: " + smudge.getName());
   }
}
ここではゲッターとセッターの両方を使用しています。まず、ゲッターを使用して猫の元の名前を取得して表示します。次に、セッターを使用して新しい名前 (「Mr. Smudge」) を割り当てます。次に、もう一度ゲッターを使用して名前を取得します (本当に変更されたかどうかを確認するため)。コンソール出力:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
それで、違いは何ですか?セッターがある場合でも、無効な値をフィールドに割り当てることができます。

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
コンソール出力:
Smudge's age: -1000 years
違いは、セッターが本格的なメソッドであることです。また、フィールドとは異なり、メソッドを使用すると、受け入れられない値を防ぐために必要な検証ロジックを作成できます。たとえば、負の数値が年齢として割り当てられるのを簡単に防ぐことができます。

public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
これで、コードが正しく動作するようになりました。

public class Main {

   public static void main(String[] args) {

       Cat smudge = new Cat("Smudge", 5, 4);
       smudge.setAge(-1000);

       System.out.println("Smudge's age: " + smudge.getAge());
   }
}
コンソール出力:
Error! Age can't be negative!
Smudge's age: 5 years
セッター内で、無効なデータを設定しようとする試みから保護する制限を作成しました。スマッジの年齢は変わっていない。常にゲッターとセッターを作成する必要があります。フィールドが取り得る値に制限がない場合でも、これらのヘルパー メソッドは害を及ぼしません。次の状況を想像してください。あなたと同僚が一緒にプログラムを書いています。パブリック フィールドを含むCatクラスを作成します。すべてのプログラマは、それらを好きなように使用しています。そして、ある晴れた日、あなたは次のように気づきます。「くそー、遅かれ早かれ、誰かが誤って重みに負の数値を割り当てるかもしれない! セッターを作成して、すべてのフィールドをプライベートにする必要がある!」それだけで、同僚が書いたすべてのコードが即座に解読されます。結局のところ、彼らは」直接猫畑。

cat.name = "Behemoth";
そして、フィールドはプライベートになり、コンパイラーは大量のエラーを吐き出します。

cat.name = "Behemoth";//error! The Cat class's name field is private!
この場合、フィールドを非表示にして、最初からゲッターとセッターを作成する方が良いでしょう。あなたの同僚は皆、それを使っていたでしょう。そして、何らかの方法でフィールド値を制限する必要があることに遅ればせながら気付いた場合は、セッター内にチェックを記述するだけで済みます。そして、誰もコードが破られることはありません。もちろん、フィールドへのアクセスを単に「読み取り専用」にしたい場合は、そのフィールドのゲッターのみを作成できます。メソッドのみを外部 (つまり、クラスの外) で使用できるようにする必要があります。データは隠蔽されるべきです。携帯電話と比較してみましょう。通常の密閉型携帯電話の代わりに、あらゆる種類の配線や回路などが突き出た、ケースが開いた携帯電話が与えられたと想像してください。しかし、電話は機能します。本当に一生懸命頑張って回路を突くと、危険にさらされる可能性さえあります。電話をかけることができる。でも、あなたは」
ゲッターとセッター - 3
代わりに、メーカーはインターフェイスを提供します。ユーザーは正しい数字を入力し、緑色の通話ボタンを押すだけで通話が始まります。彼女は回路や配線の内部で何が起こっているか、あるいはそれらがどのように仕事を遂行するかなど気にしません。この例では、会社は電話の「内部」(データ) へのアクセスを制限し、インターフェイス (メソッド) のみを公開します。その結果、ユーザーは望んでいたもの (電話をかける機能) を手に入れることができ、内部では何も壊れることはありません。 学んだことをさらに強化するには、Java コースのビデオ レッスンを視聴することをお勧めします。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION