สวัสดี! ในการบรรยายครั้งก่อน คุณได้เรียนรู้วิธีสร้างชั้นเรียนเต็มรูปแบบของคุณเองพร้อมสาขาและวิธีการต่างๆ แล้ว นี่เป็นความก้าวหน้าอย่างมาก ทำได้ดีมาก! แต่ตอนนี้ฉันต้องบอกความจริงอันไม่พึงประสงค์แก่คุณ เราไม่ได้สร้างชั้นเรียนของเราค่อนข้างถูกต้อง! ทำไม เมื่อมองแวบแรก ไม่มีข้อผิดพลาดในคลาสนี้:
ชื่อนี้มาจากภาษาอังกฤษว่า " get " - " receive " (เช่น "วิธีการรับค่าของฟิลด์") และset - " set " (เช่น "วิธีการตั้งค่าของฟิลด์") เรามาดูกันว่าพวกเขามีลักษณะอย่างไรโดยใช้คลาสของเราเป็นตัวอย่าง
การเปรียบเทียบสามารถทำได้ด้วยโทรศัพท์มือถือ ลองนึกภาพว่าแทนที่จะเปิดโทรศัพท์มือถือทั่วไป คุณได้รับโทรศัพท์ที่มีเคสแบบเปิดซึ่งมีสายไฟ วงจร ฯลฯ ทั้งหมดอยู่ ยื่นออกมา. โทรศัพท์ใช้งานได้: หากคุณพยายามอย่างหนักและเล่นซอกับไดอะแกรม คุณอาจสามารถโทรออกได้ แต่คุณอาจจะแค่ทำลายมัน บริษัทผู้ผลิตจะให้อินเทอร์เฟซแก่คุณแทน: ลูกค้าเพียงกดหมายเลขที่ต้องการ กดปุ่มสีเขียวด้วยหูโทรศัพท์ และเริ่มการโทร และเขาไม่สนใจว่าเกิดอะไรขึ้นภายในวงจรและสายไฟ และวิธีการทำงานของพวกมัน ในตัวอย่างนี้ บริษัทมีการจำกัดการเข้าถึง "ภายใน" (ข้อมูล) ของโทรศัพท์ และเหลือเพียงอินเทอร์เฟซ (วิธีการ) ภายนอกเท่านั้น เป็นผลให้ลูกค้าได้รับสิ่งที่ต้องการ (โทรออก) และจะไม่ทำลายสิ่งใดภายในอย่างแน่นอน
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
อนุญาตให้คุณกำหนดค่าบ้าๆ ให้กับฟิลด์ได้ เป็นผลให้โปรแกรมมีวัตถุที่มีสถานะไม่ถูกต้อง เช่น แมวตัวนี้ที่มีอายุ -1,000 ปี ในที่สุดเราก็ทำผิดพลาดอะไร? เมื่อเราสร้างชั้นเรียน เราก็เปิดเผยข้อมูลของมัน สาขาname
และage
อยู่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
- พวกเขาควรจะสามารถอ่านข้อมูลจากวัตถุที่มีอยู่แล้วได้ (เช่น ได้รับชื่อหรืออายุของแมวที่มีอยู่แล้ว)
- นอกจากนี้ยังควรกำหนดค่าฟิลด์ได้ด้วย แต่ในขณะเดียวกัน - เฉพาะค่าที่ถูกต้องเท่านั้น วัตถุของเราจะต้องได้รับการปกป้องจากสิ่งที่ไม่ถูกต้อง (ไม่ใช่ “อายุ = -1,000 ปี” และสิ่งที่คล้ายกัน)

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
แต่จะผ่าน gettersเท่านั้น โปรดทราบว่า getters มี access modifier 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());
}
}
ที่นี่เราใช้ทั้ง getters และ setters ขั้นแรกโดยใช้ getter เราได้รับและส่งออกชื่อเริ่มต้นของ cat ไปยังคอนโซล จากนั้นเมื่อใช้ตัวตั้งค่าname
จะมีการกำหนดค่าใหม่ให้กับฟิลด์ - "Vasily" จากนั้นเมื่อใช้ getter เราได้ชื่ออีกครั้งเพื่อตรวจสอบว่ามีการเปลี่ยนแปลงจริงหรือไม่ เอาต์พุตคอนโซล:
Изначальное 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 лет
ข้อแตกต่าง ก็ คือsetter เป็นวิธีการที่สมบูรณ์ และในวิธีการที่ไม่เหมือนกับฟิลด์ คุณสามารถใส่ตรรกะการตรวจสอบที่คุณต้องการเพื่อป้องกันค่าที่ยอมรับไม่ได้ ตัวอย่างเช่น คุณสามารถปิดใช้งานการกำหนดจำนวนลบเป็นอายุได้อย่างง่ายดาย:
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 лет
มีข้อจำกัดในตัวตั้งค่า และจะป้องกันความพยายามในการตั้งค่าข้อมูลที่ไม่ถูกต้อง อายุของ Barsik ยังคงไม่เปลี่ยนแปลง ควรสร้าง Getters และ Setters เสมอ แม้ว่าฟิลด์ของคุณจะไม่มีข้อจำกัดเกี่ยวกับค่าที่เป็นไปได้ แต่ก็จะไม่เกิดอันตรายใดๆ ลองนึกภาพสถานการณ์: คุณและเพื่อนร่วมงานกำลังเขียนโปรแกรมด้วยกัน คุณสร้างคลาสCat
ที่มีช่องสาธารณะ และโปรแกรมเมอร์ทุกคนก็ใช้คลาสนั้นตามที่พวกเขาต้องการ แล้ววันหนึ่งที่ดีก็มาถึงคุณ: “ไม่ช้าก็เร็วอาจมีคนกำหนดจำนวนลบให้กับตัวแปรโดยไม่ได้ตั้งใจweight
! เราจำเป็นต้องสร้างผู้ตั้งค่าและทำให้ทุกฟิลด์เป็นส่วนตัว!” คุณสร้างมันขึ้นมา และโค้ดทั้งหมดที่เพื่อนร่วมงานของคุณเขียนก็พังทันที ท้ายที่สุดแล้ว พวกเขาได้เขียนโค้ดจำนวนหนึ่งซึ่งเข้าถึงฟิลด์ได้Cat
โดยตรง แล้ว
cat.name = "Hippopotamus";
และตอนนี้ฟิลด์กลายเป็นส่วนตัวแล้วและคอมไพเลอร์ก็สร้างข้อผิดพลาดมากมาย!
cat.name = "Hippopotamus";//error! The name field of the Cat class has private access!
ในสถานการณ์เช่น นี้ เป็นการดีกว่าที่จะซ่อนฟิลด์และสร้าง getter-setters ตั้งแต่เริ่มต้น เพื่อนร่วมงานของคุณทุกคนจะใช้สิ่งเหล่านี้ และหากคุณรู้ตัวช้าว่าคุณจำเป็นต้องจำกัดค่าของฟิลด์ คุณก็แค่เพิ่มเช็คเข้าไปในตัวตั้งค่า และจะไม่มีใครทำลายโค้ดที่เขียนไว้แล้ว แน่นอนว่า หากคุณต้องการเข้าถึงฟิลด์ใดฟิลด์หนึ่งแบบอ่านอย่างเดียว คุณสามารถสร้าง getter หนึ่งรายการได้ “ภายนอก” นั่นคือ นอกชั้นเรียนของคุณ ควรเข้าถึงได้เฉพาะวิธีการเท่านั้น ข้อมูลจะต้องถูกซ่อนไว้

GO TO FULL VERSION