1. เพกาซัส
มาดูหลักการข้อที่สามของOOPกัน: การสืบทอด นี่เป็นหัวข้อที่น่าสนใจมากที่คุณจะใช้บ่อยๆ สำหรับผู้ที่ไม่ได้ฝึกหัด การเขียนโปรแกรมนั้นแยกไม่ออกจากเวทมนตร์ เรามาเริ่มด้วยการเปรียบเทียบที่น่าสนใจ...;
สมมติว่าคุณเป็นพ่อมดที่ต้องการสร้างม้าบิน ในแง่หนึ่ง คุณสามารถลองเสกเพกาซัสได้ แต่เนื่องจากไม่มีเพกาซีในธรรมชาติ จึงเป็นเรื่องยากมาก คุณจะต้องทำอะไรมากมายด้วยตัวเอง มันง่ายกว่ามากที่จะจับม้าและเสกปีกของมัน
ในการเขียนโปรแกรม กระบวนการนี้เรียกว่า "การสืบทอด" สมมติว่าคุณต้องเขียนคลาสที่ซับซ้อนมาก ใช้เวลานานในการเขียนโค้ดตั้งแต่ต้น จากนั้นทดสอบทุกอย่างเป็นเวลานานเพื่อค้นหาข้อผิดพลาด ทำไมต้องไปทางยาก? เป็นการดีกว่าที่จะดูว่ามีคลาสดังกล่าวอยู่แล้วหรือไม่
สมมติว่าคุณพบคลาสที่มีเมธอดที่ใช้ 80% ของฟังก์ชันที่คุณต้องการ คุณจะทำอย่างไรกับมันต่อไป? คุณเพียงแค่คัดลอกรหัสไปยังชั้นเรียนของคุณ แต่วิธีนี้มีข้อเสียหลายประการ:
- คลาสที่คุณพบอาจถูกคอมไพล์เป็น bytecode แล้ว และคุณอาจไม่มีสิทธิ์เข้าถึงซอร์สโค้ด
- มีซอร์สโค้ดของชั้นเรียน แต่คุณทำงานให้กับบริษัทที่อาจถูกฟ้องเรียกค่าเสียหายสองสามพันล้านจากการใช้โค้ดของคนอื่นถึง 6 บรรทัด แล้วนายจ้างจะฟ้องคุณ
- การทำซ้ำรหัสจำนวนมากโดยไม่จำเป็น นอกจากนี้ หากผู้เขียนคลาสภายนอกพบจุดบกพร่องในนั้นและแก้ไข คุณจะยังคงมีจุดบกพร่องนั้นอยู่
มีวิธีแก้ปัญหาที่สวยงามกว่า และไม่จำเป็นต้องเข้าถึงโค้ดของคลาสดั้งเดิมอย่างถูกกฎหมาย ใน Java คุณสามารถประกาศคลาสนั้นเป็นพาเรนต์ของคลาสของคุณ ซึ่งจะเทียบเท่ากับการเพิ่มรหัสสำหรับคลาสนั้นในรหัสของคุณเอง ชั้นเรียนของคุณจะเห็นข้อมูลทั้งหมดและวิธีการทั้งหมดของชั้นเรียนหลัก ตัวอย่างเช่น คุณสามารถทำสิ่งนี้: เราสืบทอด "ม้า" แล้วเพิ่ม "ปีก" เพื่อรับ "เพกาซัส"
2. คลาสพื้นฐานทั่วไป
มรดกสามารถใช้เพื่อวัตถุประสงค์อื่นได้เช่นกัน สมมติว่าคุณมีสิบคลาสที่คล้ายกันมาก พวกเขามีข้อมูลและวิธีการเดียวกัน คุณสามารถสร้างคลาสพื้นฐานพิเศษ ย้ายข้อมูล (และเมธอดที่เกี่ยวข้อง) ไปยังคลาสพื้นฐานนี้ และประกาศคลาสทั้งสิบเหล่านั้นให้เป็นรุ่นลูกหลาน กล่าวอีกนัยหนึ่ง ในแต่ละคลาสระบุว่าคลาสพาเรนต์คือคลาสพื้นฐานนี้
เช่นเดียวกับที่ข้อดีของสิ่งที่เป็นนามธรรมถูกเปิดเผยด้วยการห่อหุ้มด้านข้างเท่านั้น ข้อดีของการถ่ายทอดทางพันธุกรรมก็ได้รับการปรับปรุงอย่างมากเช่นกันเมื่อใช้ความหลากหลาย แต่คุณจะได้เรียนรู้เกี่ยวกับสิ่งนั้นในภายหลัง วันนี้เราจะมาดูตัวอย่างของการใช้การสืบทอด
ตัวหมากรุก
สมมติว่าเรากำลังเขียนโปรแกรมเล่นหมากรุกกับผู้ใช้ที่เป็นมนุษย์ ดังนั้นเราต้องการคลาสเพื่อเป็นตัวแทนของชิ้นส่วน พวกเขาจะเรียนวิชาอะไร?
หากคุณเคยเล่นหมากรุก คำตอบที่ชัดเจนคือKing, Queen, Bishop, Knight, Rook และ Pawn
แต่ชั้นเรียนเองก็ยังจำเป็นต้องเก็บข้อมูลเกี่ยวกับแต่ละชิ้น ตัวอย่างเช่น พิกัด x และ y และมูลค่าของชิ้นส่วน ท้ายที่สุดแล้วของบางชิ้นก็มีค่ามากกว่าชิ้นอื่นๆ
นอกจากนี้ ชิ้นส่วนจะเคลื่อนที่แตกต่างกัน ซึ่งหมายความว่าคลาสจะใช้พฤติกรรมที่แตกต่างกัน นี่คือวิธีที่คุณสามารถกำหนดให้เป็นคลาส:
|
|
|
|
|
|
นี่เป็นคำอธิบายดั้งเดิมของตัวหมากรุก
คลาสพื้นฐานทั่วไป
และนี่คือวิธีที่คุณสามารถใช้การสืบทอดเพื่อลดจำนวนโค้ด เราสามารถนำเมธอดและข้อมูลทั่วไปมาไว้ในคลาสทั่วไปได้ เราจะเรียกมันChessItem
ว่า ไม่มีประโยชน์ในการสร้างวัตถุของChessItem class
เนื่องจากคลาสไม่สอดคล้องกับตัวหมากรุกใดๆ ที่กล่าวว่าชั้นเรียนจะพิสูจน์ได้ว่ามีประโยชน์มาก:
|
|
|
|
||
|
|
|
นี่เป็นวิธีที่ยอดเยี่ยมในการลดความซับซ้อนของโค้ดสำหรับวัตถุที่คล้ายกัน ประโยชน์จะสังเกตเห็นได้ชัดเจนเป็นพิเศษเมื่อมีอ็อบเจกต์ต่างๆ นับพันรายการและคลาสหลายร้อยคลาสในโปรเจ็กต์ ดังนั้น คลาสพาเรนต์ (ฐาน) ที่เลือกอย่างเหมาะสมจึงไม่เพียงแต่ช่วยให้คุณลดความซับซ้อนของลอจิกได้มากเท่านั้น แต่ยังลดโค้ดเป็นสิบเท่าอีกด้วย
3. การสืบทอดคลาส —extends
ดังนั้นสิ่งที่ต้องทำเพื่อสืบทอดคลาส? สำหรับคลาสหนึ่งที่จะสืบทอดอีกคลาส คุณต้องเขียนextends
คีย์เวิร์ดหลังการประกาศคลาสลูก จากนั้นจึงเขียนชื่อคลาสพาเรนต์ มันมักจะมีลักษณะดังนี้:
class Descendant extends Parent
นี่คือสิ่งที่คุณต้องเขียนเมื่อประกาศคลาส Descendant อย่างไรก็ตาม คลาสสามารถสืบทอดได้เพียงคลาสเดียวเท่านั้น
ในภาพ เราเห็นว่าวัวสืบทอดหมู ไก่สืบทอดไข่ ผู้ปกครองเพียงคนเดียว! มรดกดังกล่าวไม่สมเหตุสมผลเสมอไป แต่เมื่อสิ่งที่คุณมีคือหมูและคุณต้องการวัวจริงๆ โปรแกรมเมอร์มักจะไม่สามารถต้านทานความต้องการที่จะสร้างวัวจากหมูได้
Java ไม่มีการสืบทอดหลายรายการ: คลาสไม่สามารถสืบทอดสองคลาสได้ แต่ละคลาสสามารถมีคลาสพาเรนต์ได้เพียงหนึ่งคลาสเท่านั้น หากไม่ได้ระบุคลาสพาเรนต์ คลาสพาเรนต์จะObject
เป็น
ที่กล่าวว่า Java มีการสืบทอดอินเทอร์เฟซหลายรายการ ซึ่งจะช่วยลดปัญหาได้เล็กน้อย เราจะพูดถึงอินเทอร์เฟซในภายหลัง แต่สำหรับตอนนี้ เรามาสำรวจการสืบทอดกันต่อไป