CodeGym /Blog Java /rawak /Getters dan setter
John Squirrels
Tahap
San Francisco

Getters dan setter

Diterbitkan dalam kumpulan
helo! Dalam pelajaran sebelumnya, anda telah belajar cara mengisytiharkan kelas anda sendiri yang lengkap dengan kaedah dan medan. Dalam pelajaran hari ini, kita akan bercakap tentang Getters dan Setter di Java. Ini adalah kemajuan yang serius, syabas! Tetapi sekarang saya perlu memberitahu anda kebenaran yang tidak menyenangkan. Kami tidak mengisytiharkan kelas kami dengan betul! kenapa? Pada pandangan pertama, kelas berikut tidak mempunyai sebarang kesilapan:

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!");
   }
}
Tetapi ia berlaku. Bayangkan anda sedang duduk di tempat kerja dan tulis kelas Kucing ini untuk mewakili kucing. Dan kemudian anda pulang ke rumah. Semasa anda tiada, pengaturcara lain tiba di tempat kerja. Dia mencipta kelas Utamanya sendiri , di mana dia mula menggunakan kelas Cat yang anda tulis.

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 dan bagaimana ia berlaku (mungkin lelaki itu letih atau tidak cukup tidur). Perkara lain yang penting: kelas Cat semasa kami membenarkan medan diberikan nilai yang benar-benar gila. Akibatnya, program mempunyai objek dengan keadaan tidak sah (seperti kucing ini yang berumur -1000 tahun). Jadi apakah ralat yang kami buat semasa mengisytiharkan kelas kami? Kami mendedahkan data kelas kami. Nama, umur dan medan berat adalah umum. Mereka boleh diakses di mana-mana dalam program: hanya buat objek Cat dan mana-mana pengaturcara mempunyai akses terus kepada datanya melalui pengendali titik ( . )

Cat cat = new Cat();
cat.name = "";
Di sini kami mengakses terus medan nama dan menetapkan nilainya. Kami perlu melindungi data kami daripada gangguan luar yang tidak betul. Apa yang perlu kita lakukan itu? Pertama, semua pembolehubah contoh (medan) mesti ditandakan dengan pengubah suai peribadi. Private ialah pengubah suai akses paling ketat di Java. Sebaik sahaja anda melakukan ini, medan kelas Cat tidak akan dapat diakses di luar kelas.

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!
   }
}
Pengkompil melihat ini dan serta-merta menghasilkan ralat. Sekarang bidang itu dilindungi. Tetapi ternyata kami telah menutup akses mungkin terlalu ketat: anda tidak boleh mendapatkan berat kucing sedia ada dalam program ini, walaupun anda perlu. Ini juga bukan pilihan. Pada dasarnya, kelas kami pada dasarnya tidak boleh digunakan. Sebaik-baiknya, kita perlu membenarkan beberapa jenis akses terhad:
  • Pengaturcara lain sepatutnya boleh mencipta objek Cat
  • Mereka seharusnya boleh membaca data daripada objek sedia ada (contohnya, dapatkan nama atau umur kucing sedia ada)
  • Ia juga mungkin untuk menetapkan nilai medan. Tetapi dalam berbuat demikian, hanya nilai yang sah harus dibenarkan. Objek kita harus dilindungi daripada nilai tidak sah (cth umur = -1000, dsb.).
Itulah senarai keperluan yang baik! Pada hakikatnya, semua ini mudah dicapai dengan kaedah khas yang dipanggil getter dan setter.
Getter dan setter - 2
Nama-nama ini berasal daripada "dapatkan" (iaitu "kaedah untuk mendapatkan nilai medan") dan "tetapkan" (iaitu "kaedah untuk menetapkan nilai medan"). Mari lihat penampilannya dalam kelas Cat kami :

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 boleh lihat, mereka kelihatan agak mudah :) Nama mereka selalunya terdiri daripada "get"/"set" serta nama medan yang berkaitan. Sebagai contoh, kaedah getWeight() mengembalikan nilai medan berat untuk objek yang dipanggil. Begini rupanya dalam program:

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);
   }
}
Output konsol:
Cat's name: Smudge
Cat's age: 5
Cat's weight: 4
Kini kelas lain ( Utama ) boleh mengakses medan Cat , tetapi hanya melalui getter. Ambil perhatian bahawa getter mempunyai pengubah akses awam, iaitu ia tersedia dari mana-mana sahaja dalam program. Tetapi bagaimana dengan memberikan nilai? Inilah gunanya kaedah penetap

public void setName(String name) {
   this.name = name;
}
Seperti yang anda lihat, mereka juga mudah. Kami memanggil kaedah setName() pada objek Cat , lulus rentetan sebagai hujah dan rentetan diberikan kepada medan nama objek.

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());
   }
}
Di sini kita menggunakan kedua-dua getter dan setter. Pertama, kami menggunakan pengambil untuk mendapatkan dan memaparkan nama asal kucing. Kemudian, kami menggunakan penetap untuk menetapkan nama baharu ("Mr. Smudge"). Dan kemudian kami menggunakan pengambil sekali lagi untuk mendapatkan nama (untuk menyemak sama ada ia benar-benar berubah). Output konsol:
Cat's original name: Smudge
Cat's new name: Mr. Smudge
Jadi apa bezanya? Kami masih boleh menetapkan nilai tidak sah kepada medan walaupun kami mempunyai penetap:

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());
   }
}
Output konsol:
Smudge's age: -1000 years
Perbezaannya ialah penetap adalah kaedah yang lengkap. Dan tidak seperti medan, kaedah membolehkan anda menulis logik pengesahan yang diperlukan untuk mengelakkan nilai yang tidak boleh diterima. Sebagai contoh, anda boleh dengan mudah menghalang nombor negatif daripada ditetapkan sebagai umur:

public void setAge(int age) {
   if (age >= 0) {
       this.age = age;
   } else {
       System.out.println("Error! Age can't be negative!");
   }
}
Dan kini kod kami berfungsi dengan betul!

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());
   }
}
Output konsol:
Error! Age can't be negative!
Smudge's age: 5 years
Di dalam setter, kami mencipta sekatan yang melindungi kami daripada percubaan untuk menetapkan data tidak sah. Umur Smudge tidak berubah. Anda harus sentiasa membuat getter dan setter. Walaupun tiada sekatan pada nilai yang boleh diambil oleh medan anda, kaedah pembantu ini tidak akan membahayakan. Bayangkan situasi berikut: anda dan rakan sekerja anda sedang menulis program bersama-sama. Anda membuat kelas Cat dengan medan awam. Semua pengaturcara menggunakan mereka mengikut kehendak mereka. Dan kemudian satu hari yang baik anda menyedari: "Sial, lambat laun seseorang mungkin secara tidak sengaja memberikan nombor negatif kepada pemberat! Kita perlu mencipta penetap dan menjadikan semua medan peribadi!" Anda melakukan perkara itu, dan serta-merta memecahkan semua kod yang ditulis oleh rakan sekerja anda. Lagipun, merekaMedan kucing secara langsung.

cat.name = "Behemoth";
Dan kini medan adalah peribadi dan pengkompil memuntahkan banyak ralat!

cat.name = "Behemoth";//error! The Cat class's name field is private!
Dalam kes ini, adalah lebih baik untuk menyembunyikan medan dan mencipta pengambil dan penetap dari awal lagi. Semua rakan sekerja anda akan menggunakannya. Dan jika anda terlambat menyedari bahawa anda perlu mengehadkan nilai medan, anda boleh menulis cek di dalam setter. Dan tiada kod sesiapa pun akan rosak. Sudah tentu, jika anda mahu akses kepada medan hanya "baca sahaja", anda boleh mencipta hanya pengambil untuknya. Hanya kaedah harus tersedia secara luaran (iaitu di luar kelas anda). Data harus disembunyikan. Kita boleh membuat perbandingan dengan telefon bimbit. Bayangkan bahawa bukannya telefon mudah alih tertutup biasa, anda diberikan telefon dengan sarung terbuka, dengan pelbagai wayar, litar, dll yang terkeluar. Tetapi telefon itu berfungsi: jika anda berusaha bersungguh-sungguh dan mencucuk litar, anda mungkin akan mampu membuat panggilan. Tetapi anda'
Pengambil dan penetap - 3
Sebaliknya, pengilang memberi anda antara muka: pengguna hanya memasukkan digit yang betul, menekan butang panggilan hijau dan panggilan bermula. Dia tidak peduli apa yang berlaku di dalam dengan litar dan wayar, atau bagaimana mereka menyelesaikan tugas mereka. Dalam contoh ini, syarikat mengehadkan akses kepada "bahagian dalam" (data) telefon dan hanya mendedahkan antara muka (kaedah). Akibatnya, pengguna mendapat apa yang dia mahu (keupayaan untuk membuat panggilan) dan pastinya tidak akan memecahkan apa-apa di dalamnya. Untuk mengukuhkan perkara yang anda pelajari, kami cadangkan anda menonton pelajaran video daripada Kursus Java kami
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION