บทความนี้ใช้ตัวอย่างเพื่อวิเคราะห์ความแตกต่างระหว่างการโอเวอร์โหลดและการเขียนใหม่ใน Java โดยละเอียด เพื่อนที่สนใจสามารถอ้างอิงได้
1. การโอเวอร์โหลด:
(1) การโอเวอร์โหลดเมธอดเป็นวิธีหนึ่งสำหรับคลาสในการจัดการข้อมูลประเภทต่างๆ ในลักษณะที่เป็นหนึ่งเดียว มีฟังก์ชันหลายรายการที่มีชื่อเดียวกันพร้อมๆ กัน โดยมีจำนวน/ประเภทพารามิเตอร์ต่างกัน
การบรรทุกเกินพิกัดเป็นการแสดงให้เห็นถึงความหลากหลายในชั้นเรียน
(2) การโอเวอร์โหลดเมธอด Java หมายความว่าสามารถสร้างเมธอดได้หลายวิธีในคลาสเดียว มีชื่อเดียวกัน แต่มีพารามิเตอร์และคำจำกัดความต่างกัน
เมื่อเรียกใช้เมธอด คุณจะตัดสินใจว่าจะใช้เมธอดใดโดยพิจารณาจากจำนวนและประเภทของพารามิเตอร์ที่ส่งผ่านไป
(3) เมื่อโอเวอร์โหลด ชื่อวิธีการควรเหมือนกัน แต่ประเภทพารามิเตอร์และหมายเลขต่างกัน และประเภทค่าส่งคืนอาจเหมือนหรือต่างกันได้ ไม่สามารถใช้ประเภทการส่งคืนเป็นเกณฑ์ในการแยกแยะฟังก์ชันที่โอเวอร์โหลดได้
นี่คือตัวอย่างของการโอเวอร์โหลด:
package c04.answer;//นี่คือชื่อแพ็คเกจ//นี่เป็นวิธีการเขียนโปรแกรมวิธีแรกของโปรแกรมนี้ ขั้นแรกให้สร้างอินสแตนซ์คลาส Dog ในวิธีหลัก จากนั้นใช้คีย์เวิร์ดนี้ในตัวสร้างคลาส Dog เพื่อเรียก วิธีการเปลือกไม้ที่แตกต่างกัน วิธีการเปลือกไม้ที่โอเวอร์โหลดต่างกันจะแตกต่างกันตามประเภทพารามิเตอร์ //หมายเหตุ: คอมไพลเลอร์ห้ามมิให้เรียกตัวสร้างที่อื่นยกเว้นตัวสร้าง package c04.answer;public class Dog {Dog(){this.bark();} void bark()//bark() method เป็นวิธีที่โอเวอร์โหลด {System.out.println(/"no barking!/"); this.bark(/"Female/", 3.4);} void bark(String m,double l)//หมายเหตุ: ค่าที่ส่งคืนของวิธีการโอเวอร์โหลดจะเหมือนกัน {System.out.println(/"a barking dog!/");this.bark(5, /"China/");} void bark(int a,String n)//วิธีการโอเวอร์โหลดไม่สามารถแยกแยะได้ด้วยค่าที่ส่งคืน แต่สามารถแยกแยะได้ด้วย "ประเภทพารามิเตอร์" และ "ชื่อคลาส" เท่านั้น {System.out.println(/"a Howling dog/") ; } โมฆะสาธารณะหลัก (สตริง [] args){สุนัข สุนัข = สุนัขใหม่();//dog.bark(); [หน้า]//dog.bark(/"ชาย/", /"สีเหลือง/");//dog.bark(5, / "จีน/");
2. การเอาชนะ
(1) ความแตกต่างระหว่างคลาสพาเรนต์และคลาสย่อย กำหนดฟังก์ชันของคลาสพาเรนต์ใหม่ ถ้าเมธอดที่กำหนดในคลาสย่อยมีชื่อและพารามิเตอร์เหมือนกับคลาสพาเรนต์ เราจะบอกว่าเมธอดนั้นถูกแทนที่ ใน คลาสย่อยสามารถสืบทอดเมธอดจากคลาสพาเรนต์โดยไม่ต้องเขียนเมธอดเดิมใหม่
แต่บางครั้งคลาสย่อยไม่ต้องการสืบทอดเมธอดของคลาสพาเรนต์โดยไม่เปลี่ยนแปลง แต่ต้องการทำการแก้ไขบางอย่าง ซึ่งจำเป็นต้องเขียนเมธอดใหม่
การแทนที่เมธอดเรียกอีกอย่างว่าการเขียนทับเมธอด
(2) ถ้าเมธอดในคลาสย่อยมีชื่อเมธอด ประเภทการส่งคืน และรายการพารามิเตอร์เหมือนกันกับเมธอดในคลาสพาเรนต์ เมธอดใหม่จะเขียนทับเมธอดเดิม
หากคุณต้องการวิธีการดั้งเดิมในคลาสพาเรนต์ คุณสามารถใช้คีย์เวิร์ด super ซึ่งอ้างอิงถึงคลาสพาเรนต์ของคลาสปัจจุบัน
(3) สิทธิ์ในการแก้ไขการเข้าถึงของฟังก์ชันคลาสย่อยต้องไม่ต่ำกว่าสิทธิ์ของคลาสพาเรนต์
นี่คือตัวอย่างการเขียนใหม่:
แนวคิด: กลไกในการเรียกเมธอดอ็อบเจ็กต์
lowdown ของการผูกแบบไดนามิก:
1. คอมไพเลอร์ตรวจสอบประเภทและชื่อวิธีการประกาศโดยอ็อบเจ็กต์เพื่อรับวิธีการผู้สมัครทั้งหมด ลองคอมเม้นต์การทดสอบคลาส Base ในตัวอย่างด้านบน จากนั้นการคอมไพล์จะไม่ผ่าน
2. การตัดสินใจโอเวอร์โหลด: คอมไพเลอร์ตรวจสอบประเภทพารามิเตอร์ของการเรียกเมธอด และเลือกวิธีเดียวจากวิธีการตัวเลือกข้างต้น (จะมีการแปลงประเภทโดยนัยในระหว่างกระบวนการนี้)
หากคอมไพเลอร์พบมากกว่าหนึ่งหรือไม่มีเลย คอมไพเลอร์จะรายงานข้อผิดพลาด ลองคอมเมนต์การทดสอบ (ไบต์ b) ของคลาส Base ในตัวอย่างด้านบน และผลลัพธ์ที่รันอยู่คือ 1 1
3. หากประเภทเมธอดเป็น priavte static Final และ Java ใช้การคอมไพล์แบบคงที่ คอมไพลเลอร์จะรู้แน่ชัดว่าจะเรียกใช้เมธอดใด
4. เมื่อโปรแกรมรันและใช้การเชื่อมโยงแบบไดนามิกเพื่อเรียกเมธอด เครื่องเสมือนจะต้องเรียกเวอร์ชันของเมธอดที่ตรงกับชนิดที่แท้จริงของออบเจ็กต์
ในตัวอย่าง ประเภทจริงที่ b ชี้ไปคือ TestOverriding ดังนั้น b.test(0) จึงเรียกการทดสอบของคลาสย่อย
อย่างไรก็ตาม คลาสย่อยไม่ได้แทนที่ test(byte b) ดังนั้น b.test((byte)0) เรียก test(byte b) ของคลาสพาเรนต์
หาก (ไบต์ b) ของคลาสพาเรนต์ถูกใส่เครื่องหมายความคิดเห็น ประเภทโดยนัยจะถูกแปลงเป็น int ในขั้นตอนที่สอง และในที่สุดการทดสอบ (int i) ของคลาสย่อยก็จะถูกเรียกในที่สุด
3. สรุปการเรียนรู้:
Polymorphism เป็นคุณลักษณะของการเขียนโปรแกรมเชิงวัตถุและไม่เกี่ยวข้องกับวิธีการ
พูดง่ายๆ ก็คือ วิธีการเดียวกันนี้สามารถทำการประมวลผลที่แตกต่างกันตามข้อมูลอินพุตที่แตกต่างกัน นั่นคือ วิธีการโอเวอร์โหลด - ด้วยรายการพารามิเตอร์ที่แตกต่างกัน (static polymorphism)
เมื่อคลาสย่อยสืบทอดวิธีการเดียวกันจากคลาสพาเรนต์และใช้ข้อมูลอินพุตเดียวกัน แต่ต้องการตอบสนองที่แตกต่างจากคลาสพาเรนต์ คุณจะต้องแทนที่เมธอดคลาสพาเรนต์
นั่นคือเขียนวิธีนี้ใหม่ในคลาสย่อย - พารามิเตอร์เดียวกัน การใช้งานที่แตกต่างกัน (ความหลากหลายแบบไดนามิก)
ลักษณะสำคัญสามประการของ OOP: การสืบทอด ความหลากหลาย และการห่อหุ้ม
คลาสสาธารณะ Base {void test (int i) {System.out.print (i);} การทดสอบโมฆะ (ไบต์ b) {System.out.print (b);}} คลาสสาธารณะ TestOverriding ขยายฐาน {การทดสอบโมฆะ (int i ){i++;System.out.println(i);} โมฆะสาธารณะคงหลัก (สตริง []agrs) {Base b=new TestOverriding();b.test(0)b.test((byte)0)}}
ผลลัพธ์เอาต์พุตในเวลานี้คือ 1 0 ซึ่งเป็นผลลัพธ์ของการเชื่อมโยงแบบไดนามิกที่รันไทม์
ข้อได้เปรียบหลักของการเอาชนะคือความสามารถในการกำหนดคุณลักษณะเฉพาะของคลาสย่อย:
publicclassFather{publicvoidspeak(){System.out.println(Father);}} publicclassSonextendsFather{publicvoidspeak(){System.out.println("ลูกชาย");}}
สิ่งนี้เรียกว่าความหลากหลาย วิธีการแทนที่จะมีอยู่ในความสัมพันธ์แบบสืบทอดเท่านั้น
เมื่อเมธอดคลาส Father เป็นแบบไพรเวตในตัวอย่างข้างต้น คลาส Son ไม่สามารถแทนที่เมธอดคลาส Speak() ของพ่อได้ ในขณะนี้ เมธอดคลาส Son พูด () เทียบเท่ากับเมธอด Speak() ที่กำหนดไว้ใน คลาสลูกชาย.
เมื่อเมธอดคลาส Speak() ของ Father สิ้นสุดลง ไม่ว่าวิธีการนั้นจะได้รับการแก้ไขโดยสาธารณะ ได้รับการป้องกัน หรือเป็นค่าเริ่มต้นก็ตาม คลาส Son จะไม่สามารถแทนที่เมธอดคลาส Speak() ของ Father ได้เลย
เมื่อพยายามคอมไพล์โค้ด คอมไพลเลอร์จะแสดงข้อผิดพลาด ตัวอย่าง:
publicclassFather{finalpublicvoidspeak(){System.out.println("Father");}}publicclassSonextendsFather{publicvoidspeak(){System.out.println("son");}}//คอมไพเลอร์จะรายงานข้อผิดพลาด;
เมื่อเมธอดคลาสพ่อถูกแก้ไขโดยค่าเริ่มต้น คลาสย่อยในแพ็คเกจเดียวกันจะสามารถแทนที่ได้เท่านั้น หากไม่ได้อยู่ในแพ็คเกจเดียวกัน ก็ไม่สามารถเขียนทับได้
เมื่อเมธอด Speak() ของคลาส Father ถูกสร้างต้นแบบขึ้นมา ไม่เพียงแต่จะถูกแทนที่โดยคลาสย่อยในแพ็คเกจเดียวกันเท่านั้น แต่ยังสามารถถูกแทนที่โดยคลาสย่อยของแพ็คเกจที่ต่างกันได้อีกด้วย
กฎสำหรับการเอาชนะวิธีการ:
1. รายการพารามิเตอร์จะต้องเหมือนกับวิธีการแทนที่ทุกประการ มิฉะนั้นจะไม่สามารถเรียกว่าการเขียนใหม่ แต่จะโอเวอร์โหลด
2. ประเภทการส่งคืนจะต้องเหมือนกับประเภทการส่งคืนของวิธีการแทนที่เสมอ มิฉะนั้นจะไม่สามารถเรียกว่าการเขียนทับแต่เป็นการโอเวอร์โหลด
3. ขีดจำกัดตัวแก้ไขการเข้าถึงจะต้องมากกว่าตัวแก้ไขการเข้าถึงของวิธีการแทนที่ (สาธารณะ> ป้องกัน> ค่าเริ่มต้น> ส่วนตัว)
4. วิธีการแทนที่จะต้องไม่โยนข้อยกเว้นที่ตรวจสอบใหม่หรือข้อยกเว้นที่ตรวจสอบที่กว้างกว่าการประกาศวิธีการแทนที่ ตัวอย่างเช่น:
เมธอดของคลาสพาเรนต์จะประกาศข้อยกเว้นที่เลือกไว้ IOException เมื่อแทนที่วิธีนี้ คุณจะไม่สามารถส่งข้อยกเว้นได้ คุณสามารถส่งข้อยกเว้นของคลาสย่อยของ IOException ได้เท่านั้น และคุณสามารถส่งข้อยกเว้นที่ไม่ได้ตรวจสอบได้
และกฎที่โอเวอร์โหลด:
1. ต้องมีรายการพารามิเตอร์ที่แตกต่างกัน
2. คุณสามารถมีประเภทการส่งคืนที่ไม่ตำหนิได้ ตราบใดที่รายการพารามิเตอร์แตกต่างกัน
3. สามารถมีตัวแก้ไขการเข้าถึงที่แตกต่างกันได้
4. สามารถโยนข้อยกเว้นที่แตกต่างกันได้
ความแตกต่างระหว่างการเขียนซ้ำและการโอเวอร์โหลดคือ:
การเอาชนะความหลากหลายสามารถลดจำนวนการป้อนโค้ดได้อย่างมากเมื่อเรียกใช้เมธอดที่โอเวอร์โหลด ชื่อเมธอดเดียวกันสามารถมีฟังก์ชันที่แตกต่างกันหรือคืนค่าได้ตราบใดที่พารามิเตอร์ต่างกันถูกส่งเข้าไป
ด้วยการใช้การเขียนใหม่และการโอเวอร์โหลดอย่างเหมาะสม คุณสามารถออกแบบคลาสที่มีโครงสร้างที่ชัดเจนและกระชับ อาจกล่าวได้ว่าการเขียนใหม่และการโอเวอร์โหลดมีบทบาทพิเศษในกระบวนการเขียนโค้ด