JavaRush /Blog Java /Random-MS /Getters dan setter

Getters dan setter

Diterbitkan dalam kumpulan
hello! Dalam kuliah sebelum ini, anda telah mempelajari cara membuat kelas lengkap anda sendiri, dengan bidang dan kaedah. Ini adalah kemajuan yang serius, syabas! Tetapi sekarang saya perlu memberitahu anda kebenaran yang tidak menyenangkan. Kami tidak mencipta kelas kami dengan betul! kenapa? Pada pandangan pertama, tiada ralat dalam kelas ini:
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!");
   }
}
Sebenarnya ada. Bayangkan semasa duduk di tempat kerja anda menulis kelas seperti ini Cat, menandakan kucing. Dan dia pulang ke rumah. Semasa anda tiada, pengaturcara lain datang bekerja, mencipta kelasnya sendiri Main, tempat dia mula menggunakan kelas yang anda tulis Cat.
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       cat.name = "";
       cat.age = -1000;
       cat.weight = 0;
   }
}
Tidak kira mengapa dia melakukannya atau bagaimana ia berlaku: mungkin orang itu letih atau tidak cukup tidur. Perkara lain yang penting: kelas semasa kami Catmembolehkan anda memberikan nilai gila kepada medan. Akibatnya, program ini mengandungi objek dengan keadaan yang tidak betul, seperti kucing ini dengan umur -1000 tahun. Apakah kesilapan yang akhirnya kita lakukan? Apabila kami mencipta kelas, kami mendedahkan datanya. Fields name, agedan weightberada dalam domain awam. Mereka boleh diakses di mana-mana dalam program: hanya buat objek Cat- dan itu sahaja, mana-mana pengaturcara mempunyai akses kepada datanya secara terus melalui pengendali " ."
Cat cat = new Cat();
cat.name = "";
Di sini kami terus mengakses medan namedan menetapkan nilainya. Kami perlu melindungi data kami daripada gangguan luar yang salah. Apa yang diperlukan untuk ini? Pertama, semua pembolehubah contoh (medan) mesti ditandakan dengan pengubah suai private. Private ialah pengubah suai akses paling ketat di Java. Jika anda menggunakannya, medan kelas Cattidak akan dapat diakses di luarnya.
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!
   }
}
Pengkompil melihat ini dan serta-merta menghasilkan ralat. Sekarang ladang kelihatan dilindungi. Tetapi ternyata akses kepada mereka "ketat" ditutup: program itu tidak boleh mendapatkan berat kucing yang sedia ada, jika perlu. Ini juga bukan pilihan: dalam bentuk ini kelas kami hampir mustahil untuk digunakan. Sebaik-baiknya kita perlu membenarkan beberapa jenis akses terhad kepada data:
  • Pengaturcara lain sepatutnya boleh mencipta objekCat
  • Mereka sepatutnya boleh membaca data daripada objek sedia ada (contohnya, dapatkan nama atau umur kucing yang sedia ada)
  • Ia juga mungkin untuk menetapkan nilai medan. Tetapi pada masa yang sama - hanya nilai yang betul. Objek kita mesti dilindungi daripada yang salah (tiada "umur = -1000 tahun" dan seumpamanya).
Senarai keperluan adalah baik! Tetapi sebenarnya, semua ini mudah dicapai menggunakan kaedah khas - getters dan setter .
Getter dan setter - 2
Nama itu berasal daripada bahasa Inggeris “ get ” - “ receive ” (iaitu, “kaedah untuk mendapatkan nilai medan”) dan set - “ set ” (iaitu, “kaedah untuk menetapkan nilai medan”). Mari lihat rupa mereka menggunakan kelas kami sebagai contoh 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;
   }
}
Seperti yang anda lihat, semuanya agak mudah :) Nama mereka selalunya terdiri daripada perkataan get/set + nama medan yang mereka bertanggungjawab. Sebagai contoh, kaedah getWeight()mengembalikan nilai medan weightuntuk objek yang dipanggil. Ini adalah rupa dalam program:
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);
   }
}
Output konsol:

Name кота: Барсик
Возраст кота: 5
Вес кота: 4
Sekarang dari kelas lain ( Main) terdapat akses kepada medan Cat, tetapi hanya melalui getter . Sila ambil perhatian bahawa getter mempunyai pengubah suai akses public, bermakna ia boleh diakses dari mana-mana sahaja dalam program. Bagaimana pula dengan memberikan nilai? Kaedah setter bertanggungjawab untuk ini
public void setName(String name) {
   this.name = name;
}
Kerja mereka, seperti yang anda lihat, juga mudah. Kami memanggil kaedah setName()pada objek Cat, hantar rentetan sebagai hujah, dan rentetan ini diberikan kepada medan nameobjek kami.
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());
   }
}
Di sini kami menggunakan kedua-dua getter dan setter. Pertama, menggunakan pengambil, kami menerima dan mengeluarkan nama awal kucing itu kepada konsol. Kemudian, menggunakan penetap, namenilai baharu telah diberikan kepada medannya - "Vasily". Dan kemudian, menggunakan pengambil, kami mendapat nama itu sekali lagi untuk menyemak sama ada ia benar-benar berubah. Output konsol:

Изначальное Name кота — Барсик
Новое Name кота — Васorй
Nampaknya, apakah perbezaannya? Kami juga boleh menetapkan nilai yang salah kepada medan objek, walaupun kami mempunyai penetap:
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");
   }
}
Output konsol:

Возраст Барсика — -1000 лет
Perbezaannya ialah penetap ialah kaedah yang lengkap . Dan dalam kaedah, tidak seperti medan, anda boleh meletakkan logik pengesahan yang anda perlukan untuk menghalang nilai yang tidak boleh diterima. Sebagai contoh, anda boleh melumpuhkan dengan mudah memberikan nombor negatif sebagai umur:
public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age cannot be negative!");
   }
}
Dan kini kod kami berfungsi dengan betul!
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");
   }
}
Output konsol:

Ошибка! Возраст не может быть отрицательным числом!
Возраст Барсика — 5 лет
Terdapat sekatan di dalam penetap, dan ia melindungi daripada percubaan untuk menetapkan data yang salah. Umur Barsik kekal tidak berubah. Getter dan setter hendaklah sentiasa dibuat. Walaupun medan anda tidak mempunyai sekatan pada nilai yang mungkin, tiada bahaya daripadanya. Bayangkan satu situasi: anda dan rakan sekerja anda sedang menulis program bersama-sama. Anda mencipta kelas Catdengan medan awam dan semua pengaturcara menggunakannya mengikut kehendak mereka. Dan kemudian pada suatu hari anda terfikir: “Sial, lambat laun seseorang mungkin secara tidak sengaja memberikan nombor negatif kepada pembolehubah weight! Kami perlu mencipta setter dan menjadikan semua medan peribadi!” Anda menciptanya dan semua kod yang ditulis oleh rakan sekerja anda rosak serta-merta. Lagipun, mereka telah menulis sekumpulan kod di mana mereka mengakses medan Catsecara langsung.
cat.name = "Hippopotamus";
Dan kini medan telah menjadi peribadi dan pengkompil menghasilkan banyak ralat!
cat.name = "Hippopotamus";//error! The name field of the Cat class has private access!
Dalam keadaan sedemikian, adalah lebih baik untuk menyembunyikan medan dan mencipta getter-setter dari awal lagi . Semua rakan sekerja anda akan menggunakannya, dan jika anda terlambat menyedari bahawa anda perlu mengehadkan nilai medan, anda hanya perlu menambah cek di dalam penetap. Dan tiada siapa yang akan memecahkan kod yang telah ditulis. Sudah tentu, jika anda mahukan akses baca sahaja ke medan tertentu, anda boleh membuat satu pengambil untuknya. "Di luar", iaitu, di luar kelas anda, hanya kaedah yang sepatutnya tersedia. Data mesti disembunyikan.
Pengambil dan penetap - 4
Analogi boleh dibuat dengan telefon bimbit. Bayangkan bahawa bukannya telefon mudah alih biasa dihidupkan, anda diberikan telefon dengan sarung terbuka, di mana semua wayar, litar, dsb. menjolok keluar. Telefon berfungsi: jika anda berusaha keras dan bermain-main dengan gambar rajah, anda mungkin boleh membuat panggilan. Tetapi anda mungkin hanya akan memecahkannya. Sebaliknya, syarikat pembuatan memberi anda antara muka: pelanggan hanya mendail nombor yang diperlukan, menekan butang hijau dengan telefon bimbit, dan panggilan bermula. Dan dia tidak peduli apa yang berlaku di dalam dengan litar dan wayar dan cara mereka melaksanakan tugas mereka. Dalam contoh ini, syarikat mempunyai akses terhad kepada "dalaman" (data) telefon dan hanya meninggalkan antara muka (kaedah) di luar. Akibatnya, pelanggan akan mendapat apa yang dia mahu (membuat panggilan) dan pastinya tidak akan memecahkan apa-apa di dalamnya.
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION