พิมพ์การแปลงวัตถุ Java polymorphic <br /> การแปลงประเภทวัตถุที่กล่าวถึงที่นี่หมายถึงวัตถุที่มีความสัมพันธ์การสืบทอดไม่ใช่วัตถุประเภทใด ๆ เมื่อคัดเลือกวัตถุที่ไม่มีความสัมพันธ์ในการสืบทอด Java Runtime จะทำการยกเว้น java.lang.classcastexception
ในห่วงโซ่การสืบทอดเราเรียกการแปลงคลาสย่อยเป็นคลาสแม่ "การแปลงสูงขึ้น" และการแปลงคลาสหลักเป็นระดับเด็ก "การแปลงลง"
หลายครั้งที่เรากำหนดตัวแปรเป็นประเภทของคลาสแม่ แต่อ้างถึงวัตถุของคลาสเด็ก เมื่อโปรแกรมทำงานจะใช้การเชื่อมโยงแบบไดนามิกเพื่อรับรู้การเรียกใช้วิธีย่อยนั่นคือ polymorphism
อย่างไรก็ตามบางครั้งเพื่อให้ฟังก์ชั่นที่คลาสแม่บางตัวไม่มีเราจำเป็นต้องแปลงวัตถุคลาสย่อยที่เปลี่ยนไปเป็นคลาสย่อยและเรียกใช้วิธีการย่อยซึ่งเป็นการเปลี่ยนรูปแบบลง
หมายเหตุ: วัตถุของคลาสพาเรนต์ไม่สามารถถูกส่งไปยังประเภทย่อยโดยตรงและวัตถุ subclass หลังจากการแปลงสูงขึ้นสามารถแปลงเป็นประเภท subclass อีกครั้งเท่านั้น กล่าวอีกนัยหนึ่งวัตถุคลาสย่อยจะต้องถูกเปลี่ยนขึ้นก่อนที่พวกเขาจะสามารถแปลงลงได้ โปรดดูรหัสต่อไปนี้:
การสาธิตระดับสาธารณะ {โมฆะคงที่สาธารณะ (String args []) {superclass superobj = new superclass (); วัตถุผู้ปกครองลบความคิดเห็นในบรรทัดที่ 7 และข้อยกเว้นจะถูกโยนลงไปที่รันไทม์ แต่การรวบรวมสามารถส่งผ่านได้
เนื่องจากมีความเสี่ยงในการลดลงเมื่อได้รับการอ้างอิงไปยังคลาสหลักให้แน่ใจว่าใช้ตัวดำเนินการอินสแตนซ์ของตัวดำเนินการเพื่อตรวจสอบว่าวัตถุนั้นเป็นคลาสย่อยที่คุณต้องการหรือไม่
การสาธิตระดับสาธารณะ {โมฆะสาธารณะคงที่หลัก (String args []) {superclass superobj = new superclass (); = (sonclass) superobj;} else {system.out.println ("①ไม่สามารถแปลง"); ) superobj;} else {system.out.println ("②ไม่สามารถแปลงได้"); ผลการทำงาน:
①ไม่สามารถแปลงได้
สรุป: การแปลงประเภทของวัตถุจะถูกตรวจสอบเมื่อโปรแกรมทำงาน
Java polymorphism และการผูกมัดแบบไดนามิก <br /> ใน Java ตัวแปรของคลาสแม่สามารถอ้างถึงอินสแตนซ์ของคลาสแม่หรืออินสแตนซ์ของคลาสเด็ก
โปรดอ่านโค้ดก่อน:
การสาธิตระดับสาธารณะ {โมฆะสาธารณะคงที่ (สตริง [] args) {สัตว์ obj = สัตว์ใหม่ (); .Cry ();}} คลาส Animal {// การเรียกของสัตว์ Void Cry () {System.out.println ("ฉันไม่รู้ว่าจะเรียกว่าอะไร"); Call of Cat Public Void Cry () {System.out.println ("meow ~");}} สุนัขชั้นเรียนขยายสัตว์ {// dog barking void cry () {system.out.println ("ว้าว ~"); }} ผลการทำงาน:
ฉันไม่รู้ว่าจะเรียก meow ~ wool ~ ได้อย่างไร
รหัสข้างต้นกำหนดสามชั้นคือสัตว์แมวและสุนัข ตัวแปร OBJ มีสัตว์ประเภทซึ่งสามารถชี้ไปที่อินสแตนซ์ของชั้นสัตว์เช่นเดียวกับกรณีของชั้นเรียนแมวและสุนัขซึ่งถูกต้อง นั่นคือตัวแปรของคลาสแม่สามารถอ้างถึงอินสแตนซ์ของคลาสแม่หรืออินสแตนซ์ของคลาสเด็ก โปรดทราบว่าวิธีอื่น ๆ นั้นผิดเพราะแมวทุกตัวเป็นสัตว์ แต่ไม่ใช่สัตว์ทุกตัวที่เป็นแมว
จะเห็นได้ว่า OBJ สามารถเป็นมนุษย์แมวหรือสุนัขได้ Polymorphism หมายถึงสิ่งที่มีรูปแบบหรือรูปแบบที่แตกต่างกัน
ตัวอย่างเช่น "มนุษย์" ยังมีการแสดงออกหรือการใช้งานที่แตกต่างกันมากมาย ครูหรือแพทย์ในชีวิตหน้า
มีเงื่อนไขที่จำเป็นสามประการสำหรับความหลากหลายที่มีอยู่: การสืบทอดการเขียนใหม่และตัวแปรหลักอ้างถึงวัตถุย่อย
เมื่อเรียกวิธีการโดยใช้วิธี polymorphic:
ก่อนอื่นให้ตรวจสอบว่ามีวิธีการในชั้นเรียนหลักหรือไม่
หากคลาสย่อยแทนที่วิธีการวิธีการของคลาสย่อยจะถูกเรียกมิฉะนั้นวิธีการคลาสแม่จะเรียกว่า
จากตัวอย่างข้างต้นเราจะเห็นได้ว่าข้อดีอย่างหนึ่งของ polymorphism คือเมื่อมีคลาสย่อยมากมายไม่จำเป็นต้องกำหนดตัวแปรหลายตัว โปรดดูตัวอย่างต่อไปนี้:
การสาธิตระดับสาธารณะ {โมฆะคงที่สาธารณะหลัก (String [] args) {// ด้วยความช่วยเหลือของ polymorphism เจ้าของสามารถเลี้ยงสัตว์หลายชนิด master ma = master ใหม่ (); ); ma.feed (แมวใหม่ (), ใหม่ ()); ) {system.out.println ("ฉันเป็นสัตว์เล็ก ๆ , กิน" + f.getfood ()); แมวตัวน้อยกำลังกิน " + f.getfood ());}} สุนัขชั้นเรียนขยายสัตว์ {โมฆะสาธารณะกิน (อาหาร f) {system.out.println (" ฉันเป็นสุนัขกิน " + f. getfood ()) ; String GetFood () {return "Bone"; ผลการทำงาน:
ฉันเป็นสัตว์ตัวเล็กกินของฉันเป็นแมวตัวเล็กกินปลาฉันเป็นสุนัขกินกระดูก
วิธีการป้อนของชั้นเรียนมีสองพารามิเตอร์คือประเภทสัตว์และประเภทอาหาร สัตว์ต่าง ๆ
การผูกมัดแบบไดนามิก
เพื่อที่จะเข้าใจธรรมชาติของความหลากหลายให้พูดคุยเกี่ยวกับกระบวนการโดยละเอียดของวิธีการโทร Java ด้านล่าง
1) คอมไพเลอร์ตรวจสอบประเภทการประกาศและชื่อวิธีของวัตถุ
สมมติว่า Obj.func (param) เรียกว่า OBJ เป็นวัตถุของคลาส CAT ควรสังเกตว่าอาจมีหลายวิธีที่มีชื่อที่มี func แต่พารามิเตอร์ที่แตกต่างกัน ตัวอย่างเช่นวิธีการ func (int) และ func (สตริง) อาจมีอยู่ คอมไพเลอร์จะแสดงรายการวิธีการทั้งหมดที่ชื่อ Func ในคลาส CAT และวิธีการเข้าถึงแอตทริบิวต์สาธารณะและตั้งชื่อ Func ในสัตว์ชั้นพาณิชย์
ด้วยวิธีนี้คอมไพเลอร์จะได้รับรายการวิธีการของผู้สมัครที่เป็นไปได้ทั้งหมดที่จะเรียก
2) ถัดไปตัวแก้ไขจะตรวจสอบลายเซ็นพารามิเตอร์ที่ให้ไว้เมื่อเรียกวิธีการ
หากมีวิธีการในทุกวิธีที่ชื่อ Func ที่ตรงกับลายเซ็นพารามิเตอร์ที่ให้มาแล้วเลือกวิธีนี้ กระบวนการนี้เรียกว่าความละเอียดมากเกินไป ตัวอย่างเช่นถ้าเรียกว่า func ("hello") คอมไพเลอร์จะเลือก func (สตริง) แทน func (int) เนื่องจากการมีอยู่ของการแปลงประเภทอัตโนมัติเช่น INT สามารถแปลงเป็นสองเท่า สิ้นสุดหรือหลายวิธีจับคู่จากนั้นรวบรวมข้อผิดพลาด
ด้วยวิธีนี้คอมไพเลอร์จะได้รับชื่อเมธอดและลายเซ็นพารามิเตอร์ที่ต้องเรียก
3) หาก Method Modifier เป็นแบบส่วนตัวคงที่ (คงที่และสุดท้ายจะถูกอธิบายในภายหลัง) หรือตัวสร้างคอมไพเลอร์จะสามารถรู้ได้อย่างชัดเจนว่าควรเรียกใช้วิธีใด .
ตามลำดับวิธีที่เรียกว่าขึ้นอยู่กับประเภทจริงของวัตถุและใช้การเชื่อมโยงแบบไดนามิกที่รันไทม์ ตัวอย่างเช่นเมื่อโทรหา func ("สวัสดี") ตัวแก้ไขจะใช้การเชื่อมโยงแบบไดนามิกเพื่อสร้างคำสั่งที่เรียก func (สตริง)
4) เมื่อโปรแกรมทำงานและใช้การเชื่อมโยงแบบไดนามิกเพื่อเรียกวิธีการ JVM จะเรียกวิธีการของคลาสที่เหมาะสมที่สุดสำหรับประเภทจริงของวัตถุที่อ้างอิงโดย OBJ เราสันนิษฐานว่าประเภทที่แท้จริงของ OBJ คือ CAT ซึ่งเป็นคลาสย่อยของสัตว์และมันถูกเรียกว่าถ้า Func (String) ถูกกำหนดไว้ใน CAT มิฉะนั้นจะถูกค้นหาในชั้นเรียนสัตว์และคลาสแม่
การโทรแต่ละครั้งต้องมีการค้นหาซึ่งค่อนข้างแพง ด้วยวิธีนี้เมื่อมีการเรียกวิธีการจริงเครื่องเสมือนสามารถค้นหาตารางนี้ได้เท่านั้น ในตัวอย่างด้านบน JVM ค้นหาตารางเมธอดของคลาส CAT เพื่อค้นหาวิธีที่ตรงกับการโทรกับ Func ("Hello") วิธีนี้อาจเป็น cat.func (string) หรือ iment.func (สตริง) โปรดทราบว่าหากเรียกว่า super.func ("hello") คอมไพเลอร์จะค้นหาตารางเมธอดของคลาสแม่
สมมติว่าคลาสสัตว์มีสามวิธี: cry (), getName () และ getage () จากนั้นตารางวิธีการของมันมีดังนี้:
ร้องไห้ () -> iment.cry ()
getName () -> iment.getName ()
getage () -> iment.getage ()
ในความเป็นจริงสัตว์ยังมีวัตถุคลาสแม่เริ่มต้น (ซึ่งจะอธิบายในภายหลัง) ซึ่งจะสืบทอดวิธีการของวัตถุดังนั้นวิธีการที่ระบุไว้ข้างต้นจะไม่สมบูรณ์
สมมติว่าคลาส CAT แทนที่วิธี Cry () ในคลาสสัตว์และเพิ่มวิธีการใหม่ปีนเขา () รายการพารามิเตอร์ของมันคือ:
ร้องไห้ () -> cat.cry ()
getName () -> iment.getName ()
getage () -> iment.getage ()
climbtree () -> cat.climbtree ()
เมื่อทำงานกระบวนการของการเรียกใช้วิธี obj.cry () มีดังนี้:
JVM เข้าถึงตารางวิธีการของประเภทจริงของ OBJ ซึ่งอาจเป็นตารางวิธีการของคลาสสัตว์หรือตารางวิธีการของคลาส CAT และคลาสย่อย
JVM ค้นหาวิธีการจับคู่ CRY () ในตารางเมธอดและหลังจากค้นหาแล้วคุณจะรู้ว่ามันเป็นคลาสใด
JVM เรียกวิธีนี้