แก้ไข: ฉันตอบคำถามนี้เพราะมีคนจำนวนมากเรียนรู้การเขียนโปรแกรมถามคำถามนี้และคำตอบส่วนใหญ่มีความสามารถทางเทคนิคมาก แต่พวกเขาไม่เข้าใจง่ายถ้าคุณเป็นมือใหม่ เราเป็นมือใหม่ทั้งหมดดังนั้นฉันคิดว่าฉันจะลองตอบคำถามที่เป็นมิตรกับมือใหม่มากขึ้น
สองหลักที่สำคัญคือความแตกต่างและการตรวจสอบ แม้ว่ามันจะเป็นเพียงโครงสร้างข้อมูลที่โง่
สมมติว่าเรามีคลาสง่าย ๆ นี้:
public class Bottle {
public int amountOfWaterMl;
public int capacityMl;
}
คลาสที่ง่ายมากที่เก็บของเหลวไว้ในนั้นและความสามารถของมันคืออะไร (เป็นมิลลิลิตร)
จะเกิดอะไรขึ้นเมื่อฉัน:
Bottle bot = new Bottle();
bot.amountOfWaterMl = 1500;
bot.capacityMl = 1000;
คุณไม่คาดหวังว่าจะได้ผลใช่มั้ย คุณต้องการที่จะมีการตรวจสอบสติบางอย่าง และที่แย่กว่านั้นคือถ้าฉันไม่เคยระบุความจุสูงสุดไว้ล่ะ? โอ้ที่รักเรามีปัญหา
แต่ก็มีปัญหาอื่นเช่นกัน ถ้าขวดเป็นภาชนะประเภทเดียวล่ะ? จะเกิดอะไรขึ้นถ้าเรามีภาชนะบรรจุหลายอย่างทุกอย่างเต็มไปด้วยความจุและปริมาณของเหลว หากเราสามารถสร้างอินเทอร์เฟซได้เราสามารถให้โปรแกรมที่เหลือของเรายอมรับส่วนต่อประสานนั้นและขวด jerrycans และสิ่งของทุกประเภทจะทำงานร่วมกันได้ จะไม่ดีกว่านี้หรือ เนื่องจากความต้องการวิธีการเชื่อมต่อนี้เป็นสิ่งที่ดี
เราจะได้สิ่งที่ชอบ:
public interface LiquidContainer {
public int getAmountMl();
public void setAmountMl(int amountMl);
public int getCapacityMl();
}
ที่ดี! และตอนนี้เราเพียงเปลี่ยนขวดเป็น:
public class Bottle extends LiquidContainer {
private int capacityMl;
private int amountFilledMl;
public Bottle(int capacityMl, int amountFilledMl) {
this.capacityMl = capacityMl;
this.amountFilledMl = amountFilledMl;
checkNotOverFlow();
}
public int getAmountMl() {
return amountFilledMl;
}
public void setAmountMl(int amountMl) {
this.amountFilled = amountMl;
checkNotOverFlow();
}
public int getCapacityMl() {
return capacityMl;
}
private void checkNotOverFlow() {
if(amountOfWaterMl > capacityMl) {
throw new BottleOverflowException();
}
}
ฉันจะทิ้งคำจำกัดความของ BottleOverflowException ไว้เป็นแบบฝึกหัดให้กับผู้อ่าน
ตอนนี้สังเกตว่ามันแข็งแกร่งกว่านี้มากแค่ไหน เราสามารถจัดการกับคอนเทนเนอร์ประเภทใดก็ได้ในรหัสของเราตอนนี้โดยยอมรับ LiquidContainer แทน Bottle และวิธีที่ขวดเหล่านี้จัดการกับสิ่งเหล่านี้จะแตกต่างกัน คุณสามารถมีขวดที่เขียนสถานะลงดิสก์เมื่อมีการเปลี่ยนแปลงหรือขวดที่บันทึกในฐานข้อมูล SQL หรือ GNU รู้อะไรอย่างอื่น
และสิ่งเหล่านี้สามารถมีวิธีที่แตกต่างกันในการจัดการสิ่งที่แตกต่างกัน ขวดจะตรวจสอบและถ้ามันล้นมันจะพ่น RuntimeException แต่นั่นอาจเป็นสิ่งที่ผิดที่ต้องทำ (มีการพูดคุยที่เป็นประโยชน์เกี่ยวกับการจัดการข้อผิดพลาด แต่ฉันตั้งใจทำให้มันง่ายมากที่นี่ผู้คนในความคิดเห็นน่าจะชี้ให้เห็นข้อบกพร่องของวิธีการแบบง่าย ๆ นี้))
และใช่ดูเหมือนว่าเราจะไปจากความคิดง่ายๆเพื่อรับคำตอบที่ดีกว่าอย่างรวดเร็ว
โปรดทราบว่าคุณไม่สามารถเปลี่ยนความจุขวดได้ ตอนนี้มันตั้งอยู่ในหิน คุณสามารถทำได้ด้วยการประกาศโดยขั้นสุดท้าย แต่ถ้านี่เป็นรายการคุณสามารถล้างมันเพิ่มสิ่งใหม่ ๆ ลงไปเรื่อย ๆ คุณไม่สามารถ จำกัด สิทธิ์ในการเข้าถึงอวัยวะภายใน
นอกจากนี้ยังมีสิ่งที่สามที่ทุกคนไม่ได้กล่าวถึง: getters และ setters ใช้การเรียกใช้เมธอด นั่นหมายความว่าพวกเขาดูเหมือนวิธีปกติทุกที่อื่น แทนที่จะมีไวยากรณ์เฉพาะที่แปลกประหลาดสำหรับ DTO และเนื้อหาคุณมีทุกอย่างเหมือนกัน