ในรหัสของระบบดั้งเดิมของ บริษัท ฉันเห็นรหัสจำนวนมากที่แยกแยะแอตทริบิวต์ของคลาสของวัตถุที่เลือกปฏิบัติจะถูกประมวลผลแยกกัน และดูเหมือนว่าจะเป็นวิธีมาตรฐานในการจัดการกับปัญหาที่คล้ายกัน แต่อาจมีปัญหาบางอย่าง
ก่อนอื่นเรารู้ว่า polymorphism เป็นหนึ่งในสามคุณสมบัติที่สำคัญของวัตถุที่มุ่งเน้น polymorphism ที่เรียกว่าสำหรับประเภทคอนกรีตที่แตกต่างกันเราสามารถเข้าถึงพวกเขาผ่านอินเทอร์เฟซนามธรรมเดียวกันโดยไม่ต้องเกี่ยวข้องกับรายละเอียดการใช้งานของประเภทคอนกรีต เช่นเดียวกับการออกคำบอกกล่าว: พนักงานทุกคนรวมตัวกันในจัตุรัสประชาชนเวลา 9 โมงเช้าในวันพรุ่งนี้ ไม่จำเป็นต้องแจ้งให้แต่ละคนที่อาศัยอยู่ในสถานที่ต่างกันโดยเฉพาะในเวลาที่กำหนดและเส้นทางที่จะใช้เพราะนี่เป็นความรับผิดชอบของบุคคลที่เฉพาะเจาะจงไม่ใช่ความรับผิดชอบของบุคคลที่แจ้งผู้ออกตราสาร ดังนั้นเมื่อเขียนเพื่อพิจารณาว่าชื่อคลาสจะต้องดำเนินการแยกต่างหากวิธีแรกในการคิดคือการเพิ่มอินเทอร์เฟซในคลาสพาเรนต์และทำให้เสร็จผ่านการแทนที่คลาสย่อย เปลี่ยนขนาดของรูปดังนี้:
สำหรับ i: = 0 ถึงรายการกราฟิก count - 1 ทำ
เริ่ม
กราฟิก: = รายการกราฟิก [i];
ถ้า graphic.className = 'สี่เหลี่ยมผืนผ้า' แล้ว
เริ่ม
สี่เหลี่ยมผืนผ้า (กราฟิก). ความยาว: = สี่เหลี่ยมผืนผ้า (กราฟิก) .length* 2;
สี่เหลี่ยมผืนผ้า (กราฟิก) .width: = สี่เหลี่ยมผืนผ้า (กราฟิก) .width* 2;
จบ
อื่นถ้า graph.className = 'circle' แล้ว
เริ่ม
วงกลม (กราฟิก)
จบ
จบ;
คุณสามารถเพิ่มวิธีการ "เปลี่ยน" ลงในคลาสแม่ "กราฟิก" รหัสมีดังนี้
กราฟิก = คลาส
-
ขั้นตอนการเปลี่ยนแปลง (อัตรา: จำนวนเต็ม);
จบ;
สี่เหลี่ยมผืนผ้า = คลาส
-
ขั้นตอนการเปลี่ยนแปลง (อัตรา: จำนวนเต็ม);
จบ;
วงกลม = คลาส
-
ขั้นตอนการเปลี่ยนแปลง (อัตรา: จำนวนเต็ม);
จบ;
รหัสเพื่อใช้การเปลี่ยนแปลงขนาดในคลาสกราฟิกเฉพาะ:
ขั้นตอนสี่เหลี่ยมผืนผ้าเปลี่ยน (อัตรา: จำนวนเต็ม);
เริ่ม
ยาว: = อัตรายาว*;
ความกว้าง: = ความกว้าง* อัตรา;
จบ;
ขั้นตอนการเปลี่ยนแปลง (อัตรา: จำนวนเต็ม);
เริ่ม
RADIUS: = RADIUS* อัตรา;
จบ;
หลังจากแก้ไขด้วยวิธีนี้รหัสด้านบนสามารถเรียกได้เช่นนี้:
สำหรับ i: = 0 ถึงรายการกราฟิก count - 1 ทำ
เริ่ม
กราฟิก: = รายการกราฟิก [i];
กราฟิกการเปลี่ยนแปลง (2);
จบ;
สิ่งนี้ทำให้รหัสชัดเจนยิ่งขึ้น
แน่นอนในหลายกรณีโซลูชันข้างต้นไม่สามารถใช้เมื่อตัดสินชื่อชั้นเรียน ตัวอย่างเช่นวนซ้ำ Cotrols ของ Form และดำเนินการทดลองเบื้องต้นเกี่ยวกับการควบคุมที่แตกต่างกัน เป็นไปไม่ได้ที่เราจะเพิ่มวิธีการเริ่มต้นให้กับ TCONTROL เราสามารถใช้เพื่อแยกความแตกต่างของประเภทย่อยเฉพาะเท่านั้น จากนั้นในเวลานี้ฉันขอแนะนำให้ใช้ตัวดำเนินการ IS แทนที่จะเปรียบเทียบชื่อคลาสโดยตรง
การใช้ IS คำสั่ง aObject เป็นผลลัพธ์ tform ในประเภทต่าง ๆ ของ aObject:
AObject เป็น tobject และผลลัพธ์เป็นเท็จ
AObject เป็น tform และผลลัพธ์เป็นจริง
AObject คือ TFORM1 และผลลัพธ์เป็นจริง
AObject เป็น tedit และผลลัพธ์เป็นเท็จ
AObject ไม่มีและผลลัพธ์เป็นเท็จ
จากตัวอย่างข้างต้นเราสามารถเห็นข้อได้เปรียบของการใช้งานคือ ในอนาคต tcooledit อาจถูกใช้เพื่อตกแต่งอินเทอร์เฟซดังนั้นรหัสนี้ไม่จำเป็นต้องเปลี่ยนแปลงเพราะ tcooledit เป็น tedit;
ประการที่สองหากวัตถุที่ตัดสินอาจว่างเปล่าให้ใช้ชื่อคลาสเพื่อพิจารณาว่าวัตถุนั้นได้รับการกำหนดก่อนหรือไม่มิฉะนั้นจะเกิดข้อผิดพลาดในการเข้าถึงหน่วยความจำ ตัวแทนการตัดสินจะต้องเขียนเป็น: ถ้าได้รับมอบหมาย (aobject) และ aobject.classname = 'tclass1';
เหตุผลสุดท้ายที่ไม่ได้ใช้ชื่อคลาสเป็นคำพิพากษาคือชื่อคลาสจะใช้เพื่ออธิบายคุณสมบัติของคลาส ข้อผิดพลาดเชิงตรรกะ
หาก acontrol.className = 'teidt' แล้ว // รหัสนี้จะถูกตรวจสอบเฉพาะเมื่อคุณสังเกตเห็นว่าการแก้ไขไม่ได้ทดสอบในขั้นต้น;
หาก acontrol เป็น teidt แล้ว // ไม่สามารถรวบรวมและผ่าน;
จากข้างต้นเมื่อมีความจำเป็นที่จะต้องกำหนดประเภทของวัตถุก่อนอื่นเราควรพิจารณาหลีกเลี่ยงคำสั่งการประมวลผลพิเศษผ่านการประมวลผล polymorphic กว่า classname
ในกรณีที่พิเศษมากอาจไม่ได้รับผลลัพธ์ที่ต้องการเช่น TEDIT และ TCOOLEDIT จะต้องจัดการแยกกัน ซึ่งจะดีกว่าไม่มี
Acooledit เป็น tedit // true;
acooledit.classtype = tedit // false;
acooledit.classtype = tcooledit // true;