ในภาษา Java คลาสนามธรรมและอินเทอร์เฟซเป็นสองกลไกที่รองรับการกำหนดคลาสนามธรรม เป็นเพราะกลไกทั้งสองนี้มีอยู่อย่างแม่นยำทำให้ Java ได้รับความสามารถเชิงวัตถุอันทรงพลัง มีความคล้ายคลึงกันอย่างมากระหว่างคลาสนามธรรมและอินเทอร์เฟซในแง่ของการรองรับการกำหนดคลาสนามธรรม และยังสามารถแทนที่กันได้ ดังนั้น นักพัฒนาจำนวนมากจึงดูเหมือนจะไม่เป็นทางการเกี่ยวกับการเลือกคลาสนามธรรมและอินเทอร์เฟซเมื่อกำหนดคลาสนามธรรม ในความเป็นจริง ยังคงมีความแตกต่างอย่างมากระหว่างทั้งสอง การเลือกสิ่งเหล่านี้สะท้อนถึงความเข้าใจในธรรมชาติของขอบเขตปัญหา และความเข้าใจในจุดประสงค์การออกแบบนั้นถูกต้องและสมเหตุสมผลหรือไม่ บทความนี้จะวิเคราะห์ความแตกต่างระหว่างพวกเขาและพยายามให้นักพัฒนามีพื้นฐานในการเลือกระหว่างทั้งสอง
ทำความเข้าใจคลาสนามธรรม
ทั้งคลาสนามธรรมและอินเทอร์เฟซใช้เพื่อกำหนดคลาสนามธรรมในภาษา Java (คลาสนามธรรมในบทความนี้ไม่ได้แปลจากคลาสนามธรรม แต่แสดงถึงเนื้อหานามธรรม และคลาสนามธรรมใช้เพื่อกำหนดคลาสนามธรรมในภาษา Java) โปรดใส่ใจกับความแตกต่าง) แล้วคลาสนามธรรมคืออะไร และการใช้คลาสนามธรรมมีประโยชน์อะไรกับเราบ้าง
ในแนวคิดเชิงวัตถุ เรารู้ว่าวัตถุทั้งหมดแสดงด้วยคลาส แต่สิ่งที่ตรงกันข้ามไม่เป็นความจริง ไม่ใช่ทุกคลาสจะถูกนำมาใช้เพื่ออธิบายวัตถุ หากคลาสไม่มีข้อมูลเพียงพอที่จะอธิบายวัตถุเฉพาะ คลาสดังกล่าวจะเป็นคลาสนามธรรม คลาสนามธรรมมักใช้เพื่อแสดงแนวคิดเชิงนามธรรมที่เราได้รับจากการวิเคราะห์และการออกแบบพื้นที่ที่มีปัญหา เป็นนามธรรมของชุดแนวคิดเฉพาะที่ดูแตกต่างแต่โดยพื้นฐานแล้วมีความเหมือนกัน ตัวอย่างเช่น: หากเราพัฒนาซอฟต์แวร์แก้ไขกราฟิก เราจะพบว่ามีแนวคิดเฉพาะบางอย่าง เช่น วงกลมและสามเหลี่ยมในโดเมนของปัญหา สิ่งเหล่านี้จะแตกต่างกัน แต่ทั้งหมดอยู่ในแนวคิดเรื่องรูปร่างที่แตกต่างกัน ในขอบเขตของปัญหา ถ้ามี ก็เป็นแนวคิดที่เป็นนามธรรม เป็นเพราะแนวคิดนามธรรมไม่มีแนวคิดที่เป็นรูปธรรมที่สอดคล้องกันในขอบเขตของปัญหา ดังนั้นคลาสนามธรรมที่ใช้เพื่อแสดงแนวคิดเชิงนามธรรมจึงไม่สามารถสร้างอินสแตนซ์ได้
ในฟิลด์เชิงวัตถุ คลาสนามธรรมส่วนใหญ่จะใช้สำหรับการซ่อนประเภท เราสามารถสร้างคำอธิบายเชิงนามธรรมของชุดพฤติกรรมที่ตายตัวได้ แต่พฤติกรรมชุดนี้สามารถนำไปประยุกต์ใช้อย่างเป็นรูปธรรมได้จำนวนเท่าใดก็ได้ คำอธิบายนามธรรมนี้เป็นคลาสนามธรรม และชุดของการใช้งานที่เป็นรูปธรรมที่เป็นไปได้นี้จะแสดงด้วยคลาสที่ได้รับที่เป็นไปได้ทั้งหมด โมดูลสามารถทำงานบนเนื้อหาที่เป็นนามธรรมได้ เนื่องจากโมดูลอาศัยนามธรรมคงที่ จึงไม่สามารถแก้ไขได้ ในเวลาเดียวกัน พฤติกรรมของโมดูลนี้สามารถขยายได้โดยการได้รับจากนามธรรมนี้ ผู้อ่านที่คุ้นเคยกับ OCP ต้องรู้ว่าเพื่อให้บรรลุ OCP (หลักการเปิด-ปิด) หนึ่งในหลักการสำคัญของการออกแบบเชิงวัตถุ คลาสนามธรรมเป็นกุญแจสำคัญ
ดูคลาสนามธรรมและอินเทอร์เฟซจากระดับคำจำกัดความทางไวยากรณ์
ในระดับไวยากรณ์ ภาษา Java จัดเตรียมวิธีการนิยามที่แตกต่างกันสำหรับคลาสนามธรรมและอินเทอร์เฟซ ต่อไปนี้เป็นตัวอย่างของการกำหนดคลาสนามธรรมที่ชื่อว่า Demo เพื่อแสดงความแตกต่างนี้
วิธีการกำหนดคลาสนามธรรมสาธิตโดยใช้คลาสนามธรรมมีดังนี้:
การสาธิตคลาสนามธรรม {
โมฆะนามธรรม method1();
บทคัดย่อเป็นโมฆะ method2();
-
-
วิธีการกำหนดคลาสนามธรรมสาธิตโดยใช้อินเทอร์เฟซมีดังนี้:
อินเทอร์เฟซสาธิต{
เป็นโมฆะ method1();
เป็นโมฆะ method2();
-
-
ในวิธีคลาสนามธรรม Demo สามารถมีสมาชิกข้อมูลของตัวเองหรือวิธีสมาชิกที่ไม่ใช่นามธรรมได้ ในวิธีอินเทอร์เฟซ Demo สามารถมีสมาชิกข้อมูลคงที่เท่านั้นที่ไม่สามารถแก้ไขได้ (นั่นคือ จะต้องเป็นข้อมูลขั้นสุดท้าย) สมาชิกโดยทั่วไปไม่ได้ถูกกำหนดไว้ในอินเทอร์เฟซ) และวิธีการสมาชิกทั้งหมดเป็นแบบนามธรรม ในแง่หนึ่งอินเทอร์เฟซเป็นรูปแบบพิเศษของคลาสนามธรรม
จากมุมมองของการเขียนโปรแกรม ทั้งคลาสนามธรรมและอินเทอร์เฟซสามารถใช้เพื่อนำแนวคิดของ "การออกแบบตามสัญญา" ไปใช้ อย่างไรก็ตาม ยังคงมีความแตกต่างบางประการในการใช้งานเฉพาะ
ประการแรก คลาสนามธรรมแสดงถึงความสัมพันธ์แบบสืบทอดในภาษา Java และคลาสสามารถใช้ความสัมพันธ์แบบสืบทอดได้เพียงครั้งเดียวเท่านั้น (เนื่องจาก Java ไม่รองรับการสืบทอดหลายรายการ - บันทึกการโอนย้าย) อย่างไรก็ตาม คลาสสามารถใช้หลายอินเทอร์เฟซได้ บางทีนี่อาจเป็นการพิจารณาประนีประนอมโดยนักออกแบบภาษา Java เมื่อพิจารณาถึงการสนับสนุนของ Java สำหรับการสืบทอดหลายรายการ
ประการที่สอง ในคำจำกัดความของคลาสนามธรรม เราสามารถกำหนดพฤติกรรมเริ่มต้นของเมธอดได้ แต่ในคำจำกัดความของอินเทอร์เฟซ วิธีการไม่สามารถมีพฤติกรรมเริ่มต้นได้ เพื่อหลีกเลี่ยงข้อจำกัดนี้ ต้องใช้ผู้รับมอบสิทธิ์ แต่จะเพิ่มความซับซ้อนและบางครั้งก็ทำให้เกิดปัญหามากมาย
มีปัญหาร้ายแรงอีกประการหนึ่งที่ไม่สามารถกำหนดพฤติกรรมเริ่มต้นในคลาสนามธรรมได้ ซึ่งก็คืออาจทำให้เกิดปัญหาในการบำรุงรักษาได้ เพราะถ้าคุณต้องการแก้ไขอินเทอร์เฟซของคลาสในภายหลัง (โดยปกติจะแสดงด้วยคลาสนามธรรมหรืออินเทอร์เฟซ) เพื่อปรับให้เข้ากับสถานการณ์ใหม่ (เช่น การเพิ่มวิธีการใหม่หรือการเพิ่มพารามิเตอร์ใหม่ให้กับวิธีการที่ใช้แล้ว) มันจะยุ่งยากมาก อาจใช้เวลานาน (โดยเฉพาะหากมีคลาสที่ได้รับหลายคลาส) แต่หากอินเทอร์เฟซถูกใช้งานผ่านคลาสนามธรรม คุณอาจต้องแก้ไขพฤติกรรมเริ่มต้นที่กำหนดไว้ในคลาสนามธรรมเท่านั้น
ในทำนองเดียวกัน หากไม่สามารถกำหนดพฤติกรรมเริ่มต้นในคลาสนามธรรมได้ การใช้เมธอดเดียวกันจะปรากฏในทุกคลาสที่ได้รับของคลาสนามธรรม ซึ่งละเมิดหลักการ "กฎเดียว สถานที่เดียว" ส่งผลให้เกิดการทำสำเนาโค้ด ซึ่งเป็นอันตรายต่อเช่นกัน อนาคต ดังนั้นควรระมัดระวังในการเลือกระหว่างคลาสนามธรรมและอินเทอร์เฟซ
การดูคลาสนามธรรมและอินเทอร์เฟซจากระดับแนวคิดการออกแบบ
ข้างต้นกล่าวถึงความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซจากมุมมองของคำจำกัดความทางไวยากรณ์และการเขียนโปรแกรมเป็นหลัก ความแตกต่างในระดับเหล่านี้ค่อนข้างต่ำและไม่จำเป็น ส่วนนี้จะวิเคราะห์ความแตกต่างระหว่างคลาสนามธรรมและอินเทอร์เฟซจากอีกระดับหนึ่ง: แนวคิดการออกแบบที่สะท้อนให้เห็นในทั้งสอง ผู้เขียนเชื่อว่าเพียงการวิเคราะห์จากระดับนี้เท่านั้นที่เราจะสามารถเข้าใจสาระสำคัญของทั้งสองแนวคิดได้
ดังที่ได้กล่าวไว้ก่อนหน้านี้ คลาสนามธรรมรวบรวมความสัมพันธ์การสืบทอดในภาษา Java เพื่อให้ความสัมพันธ์การสืบทอดสมเหตุสมผล ต้องมีความสัมพันธ์ "is-a" ระหว่างคลาสพาเรนต์และคลาสที่ได้รับ นั่นคือ คลาสพาเรนต์และ คลาสที่ได้รับมีแนวคิดเดียวกันโดยพื้นฐานแล้วมันควรจะเหมือนกัน นี่ไม่ใช่กรณีของอินเทอร์เฟซ ผู้ดำเนินการของอินเทอร์เฟซและคำจำกัดความของอินเทอร์เฟซไม่จำเป็นต้องสอดคล้องกันในแนวความคิด แต่ใช้เฉพาะสัญญาที่กำหนดโดยอินเทอร์เฟซเท่านั้น เพื่อให้การสนทนาเข้าใจได้ง่ายขึ้น เราจะแสดงตัวอย่างง่ายๆ ด้านล่างนี้
ลองพิจารณาตัวอย่างดังกล่าว สมมติว่ามีแนวคิดเชิงนามธรรมเกี่ยวกับประตูในโดเมนปัญหาของเรา ในตอนนี้ เราสามารถกำหนดประเภทที่แสดงถึงแนวคิดเชิงนามธรรมผ่านคลาสเชิงนามธรรมหรือส่วนต่อประสาน วิธีการมีดังนี้:
ใช้คลาสนามธรรมเพื่อกำหนดประตู:
ประตูคลาสนามธรรม{
โมฆะนามธรรมเปิด ();
โมฆะนามธรรมปิด ();
-
กำหนดประตูโดยใช้วิธีอินเทอร์เฟซ:
ประตูอินเตอร์เฟส{
เป็นโมฆะเปิด ();
เป็นโมฆะปิด ();
-
ประเภทประตูเฉพาะอื่นๆ สามารถขยายประตูที่กำหนดโดยใช้วิธีคลาสนามธรรม หรือนำประตูที่กำหนดโดยใช้วิธีอินเทอร์เฟซไปใช้ ดูเหมือนว่าไม่มีความแตกต่างอย่างมากระหว่างการใช้คลาสนามธรรมและอินเทอร์เฟซ
หากตอนนี้ประตูจำเป็นต้องมีฟังก์ชั่นสัญญาณเตือน เราควรออกแบบโครงสร้างคลาสสำหรับตัวอย่างนี้อย่างไร (ในตัวอย่างนี้ เพื่อแสดงความแตกต่างในแนวคิดการออกแบบระหว่างคลาสนามธรรมและอินเทอร์เฟซเป็นหลัก และปัญหาอื่นๆ ที่ไม่เกี่ยวข้องได้ถูกทำให้ง่ายขึ้นหรือถูกละเลย) วิธีแก้ปัญหาที่เป็นไปได้แสดงไว้ด้านล่าง และตัวเลือกต่างๆ เหล่านี้ได้รับการวิเคราะห์จากระดับแนวคิดการออกแบบ
แนวทางแก้ไขที่หนึ่ง:
เพียงเพิ่มวิธีการเตือนให้กับคำจำกัดความของประตูดังต่อไปนี้:
ประตูคลาสนามธรรม{
โมฆะนามธรรมเปิด ();
โมฆะนามธรรมปิด ();
สัญญาณเตือนโมฆะนามธรรม ();
-
หรือ
ประตูอินเตอร์เฟส{
เป็นโมฆะเปิด ();
เป็นโมฆะปิด ();
สัญญาณเตือนเป็นโมฆะ ();
-
จากนั้น AlarmDoor พร้อมฟังก์ชั่นสัญญาณเตือนจะถูกกำหนดดังนี้:
คลาส AlarmDoor ขยายประตู {
เป็นโมฆะเปิด(){…}
เป็นโมฆะปิด(){…}
สัญญาณเตือนเป็นโมฆะ(){…}
-
หรือ
คลาส AlarmDoor ใช้ Door {
โมฆะเปิด(){…}
เป็นโมฆะปิด(){…}
สัญญาณเตือนเป็นโมฆะ(){…}
-
วิธีการนี้ฝ่าฝืน ISP (Interface Segregation Principle) ซึ่งเป็นหลักการสำคัญในการออกแบบเชิงวัตถุ ในคำจำกัดความของ Door วิธีพฤติกรรมโดยธรรมชาติของแนวคิด Door เองนั้นผสมกับวิธีพฤติกรรมของแนวคิด "การเตือน" อื่น ปัญหาหนึ่งที่เกิดจากสิ่งนี้คือโมดูลที่ใช้เฉพาะแนวคิดของประตูเท่านั้นที่จะเปลี่ยนแปลงเนื่องจากการเปลี่ยนแปลงในแนวคิดของ "สัญญาณเตือน" (เช่น การแก้ไขพารามิเตอร์ของวิธีการเตือน) และในทางกลับกัน
แนวทางที่สอง:
เนื่องจากการเปิด ปิด และสัญญาณเตือนเป็นของสองแนวคิดที่แตกต่างกัน ตามหลักการของ ISP จึงควรกำหนดไว้ในคลาสนามธรรมที่แสดงถึงแนวคิดทั้งสองนี้ วิธีการกำหนดคือ: แนวคิดทั้งสองถูกกำหนดโดยใช้วิธีคลาสนามธรรม แนวคิดทั้งสองถูกกำหนดโดยใช้วิธีอินเทอร์เฟซ แนวคิดหนึ่งถูกกำหนดโดยใช้วิธีคลาสนามธรรม และแนวคิดอื่นถูกกำหนดโดยใช้วิธีอินเทอร์เฟซ
เห็นได้ชัดว่า เนื่องจากภาษา Java ไม่สนับสนุนการสืบทอดหลายรายการ จึงเป็นไปไม่ได้ที่จะกำหนดทั้งสองแนวคิดโดยใช้คลาสนามธรรม สองวิธีหลังนี้เป็นไปได้ทั้งคู่ แต่ทางเลือกของพวกเขาสะท้อนถึงความเข้าใจในแก่นแท้ของแนวคิดในขอบเขตปัญหา และการสะท้อนถึงความตั้งใจในการออกแบบนั้นถูกต้องและสมเหตุสมผลหรือไม่ มาวิเคราะห์และอธิบายทีละเรื่องกัน
หากทั้งสองแนวคิดถูกกำหนดโดยใช้วิธีอินเทอร์เฟซ ก็จะสะท้อนถึงปัญหาสองประการ: 1. เราอาจไม่เข้าใจโดเมนของปัญหาอย่างชัดเจน AlarmDoor เป็นประตูหรือสัญญาณเตือนหรือไม่ 2. หากไม่มีปัญหากับความเข้าใจของเราเกี่ยวกับโดเมนของปัญหา เช่น จากการวิเคราะห์โดเมนของปัญหา เราพบว่า AlarmDoor มีแนวความคิดที่สอดคล้องกับ Door จากนั้นเราจะไม่สามารถเปิดเผยจุดประสงค์การออกแบบของเราได้อย่างถูกต้องเมื่อนำไปใช้งาน เนื่องจาก คำจำกัดความของแนวคิดทั้งสองนี้ (ทั้งคู่กำหนดโดยใช้วิธีอินเทอร์เฟซ) ไม่ได้สะท้อนความหมายข้างต้น
หากความเข้าใจของเราเกี่ยวกับโดเมนของปัญหาคือ: AlarmDoor นั้นเป็นประตูโดยพื้นฐานแล้ว และมันก็มีหน้าที่ในการเตือนด้วย เราควรออกแบบและนำไปปฏิบัติอย่างไรให้สะท้อนความหมายของเราได้ชัดเจน? ตามที่กล่าวไว้ก่อนหน้านี้ คลาสนามธรรมแสดงถึงความสัมพันธ์แบบสืบทอดในภาษา Java และความสัมพันธ์แบบสืบทอดโดยพื้นฐานแล้วคือความสัมพันธ์แบบ "is-a" ดังนั้นสำหรับแนวคิดของ Door เราควรใช้วิธีคลาสนามธรรมเพื่อกำหนดมัน นอกจากนี้ AlarmDoor ยังมีฟังก์ชันการเตือน ซึ่งหมายความว่าสามารถดำเนินการลักษณะการทำงานที่กำหนดไว้ในแนวคิดการเตือนได้สำเร็จ ดังนั้นจึงสามารถกำหนดแนวคิดการเตือนผ่านอินเทอร์เฟซได้ ดังที่แสดงด้านล่าง:
ประตูคลาสนามธรรม{
โมฆะนามธรรมเปิด ();
โมฆะนามธรรมปิด ();
-
อินเตอร์เฟซปลุก{
สัญญาณเตือนเป็นโมฆะ ();
-
class Alarm Door ขยาย Door ดำเนินการ Alarm {
โมฆะเปิด(){…}
เป็นโมฆะปิด(){…}
สัญญาณเตือนเป็นโมฆะ(){…}
-
วิธีการนำไปใช้นี้สามารถสะท้อนถึงความเข้าใจของเราในขอบเขตปัญหาได้อย่างชัดเจน และเปิดเผยความตั้งใจในการออกแบบของเราได้อย่างถูกต้อง ในความเป็นจริงคลาสนามธรรมแสดงถึงความสัมพันธ์ "is-a" และอินเทอร์เฟซแสดงถึงความสัมพันธ์ "like-a" คุณสามารถใช้เป็นพื้นฐานในการเลือกได้ แน่นอนว่าสิ่งนี้ขึ้นอยู่กับความเข้าใจในโดเมนของปัญหา ตัวอย่าง: หากเราหาก AlarmDoor เป็นสัญญาณเตือนตามแนวคิดและมีหน้าที่เป็นประตู จะต้องกลับคำนิยามข้างต้น
สรุป
1.คลาสนามธรรมแสดงถึงความสัมพันธ์การสืบทอดในภาษา Java และคลาสสามารถใช้ความสัมพันธ์การสืบทอดได้เพียงครั้งเดียว อย่างไรก็ตาม คลาสสามารถใช้หลายอินเทอร์เฟซได้
2. ในคลาสนามธรรม คุณสามารถมีสมาชิกข้อมูลของคุณเองได้ และคุณยังสามารถมีวิธีสมาชิกที่ไม่เป็นนามธรรมได้ด้วย แต่ในอินเทอร์เฟซ คุณสามารถมีได้เฉพาะสมาชิกข้อมูลคงที่ที่ไม่สามารถแก้ไขได้ (นั่นคือ จะต้องเป็นแบบคงที่ขั้นสุดท้าย แต่โดยทั่วไปแล้วในอินเทอร์เฟซข้อมูลสมาชิกไม่ได้ถูกกำหนดไว้) และวิธีการสมาชิกทั้งหมดนั้นเป็นนามธรรม
3.คลาสนามธรรมและอินเทอร์เฟซสะท้อนแนวคิดการออกแบบที่แตกต่างกัน ในความเป็นจริง คลาสนามธรรมแสดงถึงความสัมพันธ์ "is-a" และอินเทอร์เฟซแสดงถึงความสัมพันธ์ "like-a"
4. คลาสที่ใช้คลาสนามธรรมและอินเทอร์เฟซจะต้องใช้วิธีการทั้งหมดในคลาสนั้น คลาสนามธรรมสามารถมีวิธีที่ไม่ใช่นามธรรมได้ ไม่สามารถใช้วิธีการนำไปใช้ในอินเทอร์เฟซได้
5. ตัวแปรที่กำหนดในอินเทอร์เฟซเป็นแบบสาธารณะคงที่สุดท้ายตามค่าเริ่มต้น และต้องระบุค่าเริ่มต้น ดังนั้นจึงไม่สามารถกำหนดใหม่ในคลาสการใช้งาน และไม่สามารถเปลี่ยนแปลงค่าได้
6. ตัวแปรในคลาสนามธรรมนั้นเป็นมิตรตามค่าเริ่มต้น และสามารถกำหนดค่าใหม่ในคลาสย่อยหรือกำหนดใหม่ได้
7. วิธีการในอินเทอร์เฟซเป็นแบบสาธารณะและแบบนามธรรมตามค่าเริ่มต้น
สรุปแล้ว
คลาสนามธรรมและอินเทอร์เฟซเป็นสองวิธีในการกำหนดคลาสนามธรรมในภาษา Java และพวกมันคล้ายกันมาก อย่างไรก็ตาม การเลือกมักจะสะท้อนถึงความเข้าใจในแก่นแท้ของแนวคิดในขอบเขตของปัญหา และการสะท้อนของความตั้งใจในการออกแบบนั้นถูกต้องและสมเหตุสมผลหรือไม่ เนื่องจากสิ่งเหล่านี้แสดงความสัมพันธ์ที่แตกต่างกันระหว่างแนวคิด (แม้ว่าพวกเขาจะสามารถบรรลุฟังก์ชันที่ต้องการทั้งหมดก็ตาม) นี่เป็นการใช้ภาษาแบบสำนวนจริงๆ ฉันหวังว่าผู้อ่านจะเข้าใจได้อย่างรอบคอบ