การวิเคราะห์ความหลากหลายใน Delphi
1 polymorphism คืออะไร? 2
1.1 แนวคิด 2
1.2 ความหมายของ polymorphism 2
1.3 วิธีการใช้ polymorphism ใน Delphi? 2
1.3.1 มรดก 2
1.3.2 วิธีการเสมือนจริงวิธีการแบบไดนามิกและวิธีการนามธรรม, VMT/DMT, การผูกคงที่และการเชื่อมโยงแบบไดนามิก 2
1.3.3 โอเวอร์โหลดและ polymorphism 2
1.4 การอภิปรายเกี่ยวกับ polymorphic species 2
1.4.1 polymorphism สองระดับ 2
1.4.2 polymorphism ที่ไม่ปลอดภัย 2
2 แอปพลิเคชันของ polymorphism ใน VCL2
2.1 วิธีการก่อสร้างและการทำลายล้าง 2
2.2 tstrings2
2.3 คนอื่น ๆ (โปรดเพิ่มวิญญาณ) 2
บทคัดย่อ polymorphism เป็นวิญญาณของวัตถุที่มุ่งเน้น
ความหลากหลาย ของคำหลัก , การสืบทอด, การมุ่งเน้นวัตถุ, VCL, วิธีการเสมือน, แทนที่
คำถาม
Polymorphism เป็นวิญญาณของวัตถุที่มุ่งเน้นและการทำความเข้าใจ polymorphism เป็นหนึ่งในกุญแจสำคัญในการใช้เทคโนโลยีที่มุ่งเน้นวัตถุ แต่ polymorphism คืออะไร? ความหมายของ polymorphism คืออะไร? จะบรรลุความหลากหลายได้อย่างไร? ฉันสามารถเข้าใจแนวคิดเรื่องความหลากหลาย แต่ฉันไม่รู้วิธีใช้และใช้เมื่อใด โปรดอ่านบทความนี้โดยละเอียด
การวิเคราะห์ผู้เชี่ยวชาญ
โลก (วัตถุเช่นวัตถุ) มีการเปลี่ยนแปลงตลอดเวลา ในภาษาคอมพิวเตอร์ อุตสาหกรรมซอฟต์แวร์ทั้งหมดคือการเปลี่ยนแปลงของโลก เครื่องมือพัฒนาที่มุ่งเน้นได้ปรากฏขึ้นเช่น VC, Delphi และ BCB การออกแบบที่มุ่งเน้น (OOD), การวิเคราะห์เชิงวัตถุ (OOA) และฐานข้อมูลเชิงวัตถุ (OODB)) เทคโนโลยีเชิงวัตถุได้แทรกซึมเข้าไปในฟิลด์ซอฟต์แวร์ทั้งหมดและวิธีการคิดของโปรแกรมเมอร์ก็ผ่านการเปลี่ยนแปลงพื้นฐาน! ในสายตาของนักทฤษฎีการทำให้บริสุทธิ์ของ OO ทุกอย่างเป็นวัตถุ! แม้ว่าฉันจะไม่เห็นด้วยกับมุมมองนี้ แต่ฉันคิดว่าวิธีการนี้สอดคล้องกับนิสัยการคิดของผู้คนมากที่สุด สมองตั้งแต่นั้นมาฉันได้รับการปลดปล่อย! นี่คือการปฏิวัติ!
เนื้อหาหลักของวัตถุที่มุ่งเน้นคือวัตถุการห่อหุ้มมรดกความหลากหลายและกลไกข้อความ Master Polymorphism คุณจะไม่ได้เรียนรู้เทคโนโลยีเชิงวัตถุ
1 polymorphism คืออะไร?
1.1 แนวคิด
มีความคิดเห็นที่แตกต่างกันมากมายเกี่ยวกับแนวคิดของ polymorphism และต่อไปนี้เป็นคำสั่งตัวแทนหลายประการ:
“ ความสามารถในการจัดการมากกว่าหนึ่งประเภทด้วยตัวชี้หรืออ้างอิงถึงคลาสพื้นฐานที่พูดถึงว่าเป็น polymorphism” (ไพรเมอร์ C ++, หน้า 838) นั่นคือความสามารถในการใช้งานวัตถุของหลายคลาส (คลาสพื้นฐานและคลาสที่ได้รับ) โดยใช้พอยน์เตอร์/การอ้างอิงไปยังคลาสพื้นฐานเรียกว่า polymorphism ได้รับการพิจารณาจากมุมมองของการใช้ภาษา
"polymorphism ให้มิติอื่นของการแยกอินเทอร์เฟซออกจากการนำไปใช้เพื่อแยกสิ่งที่จากวิธี" ("คิดใน edtion java" ครั้งที่ 3) นั่นคือ polymorphism ให้อินเทอร์เฟซแยกและการใช้งานอีกชนิดหนึ่ง (เช่น "สิ่งที่ต้องทำ" และสิ่งที่ต้องทำ " "วิธีทำสเกล" แยก " ได้รับการพิจารณาจากมุมมองการออกแบบ
“ ความสามารถในการใช้นิพจน์เดียวกันเพื่อแสดงถึงการดำเนินการที่แตกต่างกันเรียกว่า polymorphism” (หลักการเชิงวัตถุและการปฏิบัติฉบับที่ 3 รุ่นที่ 16) พูดง่ายๆคือ polymorphism คือ "การแสดงออกเหมือนกันการดำเนินการที่แตกต่างกัน" หรืออาจกล่าวได้ว่า "คำสั่งเดียวกันการดำเนินการที่แตกต่างกัน" นี่คือจากมุมมองของความหมายเชิงวัตถุ
ทั้งสามข้อความอธิบายสาระสำคัญของความหลากหลายจากมุมมองที่แตกต่างกัน คำแถลงที่สามมีความแม่นยำเป็นพิเศษ
ให้ฉันอธิบายความหมายของประโยคนี้ก่อน:
นิพจน์เดียวกัน - การโทรฟังก์ชั่น
การดำเนินการที่แตกต่างกัน - มีการดำเนินการที่แตกต่างกันตามวัตถุที่แตกต่างกัน
ตัวอย่างเช่นใน บริษัท มีพนักงานหลายคนที่มีความรับผิดชอบที่แตกต่างกัน (โปรแกรมเมอร์พนักงานขายผู้จัดการเอกสาร ฯลฯ ) ที่ทำสิ่งต่าง ๆ เมื่อพวกเขา "ไปทำงาน" (ยังถือได้ว่าเป็นตรรกะทางธุรกิจ) เรา บทคัดย่องานของพวกเขาในฐานะ "ทำงาน" และความสัมพันธ์มีดังนี้:
พนักงาน
/ | / —— ความสัมพันธ์ระหว่างกัน
ผู้จัดการพนักงานขายโปรแกรมเมอร์
เมื่อชั่วโมงทำงานมาทุกวันมันก็เทียบเท่ากับการออกคำสั่งเช่นนี้:
"พนักงาน. เริ่มทำงาน" (นิพจน์เดียวกัน)
หลังจากพนักงานแต่ละคนได้รับคำสั่งนี้ (คำสั่งเดียวกัน) เขา "เริ่มทำงาน" แต่สิ่งที่พวกเขาทำคืองานของพวกเขาโปรแกรมเมอร์เริ่ม "การเข้ารหัส" พนักงานขายเริ่ม "ติดต่อธุรกิจ" และผู้จัดการวัฒนธรรมเริ่มต้น " การจัดระเบียบเอกสาร” นั่นคือ "นิพจน์เดียวกัน (การเรียกใช้ฟังก์ชัน) การดำเนินการที่แตกต่างกัน (ดำเนินการตามวัตถุต่าง ๆ ในช่วงเวลารันไทม์)"
จากมุมมองของการใช้ภาษาของ polymorphism polymorphism ทำได้โดยการเรียกใช้วิธีการเสมือนจริงโดยพอยน์เตอร์คลาสพื้นฐานหรือการอ้างอิงไปยังวัตถุที่ชี้ไปที่คลาสที่ได้รับ ต่อไปนี้คือการใช้ภาษา Pascal Object
temployee = class // พนักงานนามธรรมในชั้นเรียนนามธรรม
สาธารณะ
ขั้นตอนการเริ่มต้นทำงานเสมือนจริง; บทคัดย่อ;
{ฟังก์ชั่นบทคัดย่อ (เช่นฟังก์ชั่นเสมือนจริงใน C ++) ไม่ทำอะไรเลยความหมายที่แท้จริงคือการสำรองอินเทอร์เฟซก่อน โอเวอร์โหลดใช้มันในคลาสที่ได้รับ -
จบ;
tprogramer = คลาส (temployee) // โปรแกรมเมอร์
สาธารณะ
ขั้นตอนการเริ่มต้น
จบ;
tbusinessman = คลาส (temployee) // พนักงานขาย
สาธารณะ
ขั้นตอนการเริ่มต้น
จบ;
tDocManager = คลาส (temployee) // ตัวจัดการข้อความ
สาธารณะ
ขั้นตอนการเริ่มต้น
จบ;
ขั้นตอน tprogramer.startworking;
เริ่ม
ShowMessage ('การเข้ารหัส');
จบ;
{tbusinessman}
ขั้นตอน tbusinessman.startworking;
เริ่ม
ShowMessage ('การเชื่อมโยงธุรกิจ');
จบ;
{tDocManager}
ขั้นตอน TDOCMANAGER.STARTWORKING;
เริ่ม
ShowMessage ('การจัดการเอกสาร');
จบ;
ขั้นตอน tform1.button1click (ผู้ส่ง: tobject);
const
enum = 3;
วาจา
พนักงาน: อาร์เรย์ของ Temployee;
ฉัน: จำนวนเต็ม;
เริ่ม
setLength (พนักงาน, enum);
พนักงาน [0]: = tprogramer.create;
// อ้างถึงพนักงานชั้นฐาน [0] เพื่อชี้ไปที่วัตถุ tprogramer ที่เพิ่งสร้างขึ้น
พนักงาน [1]: = tbusinessman.create;
// อ้างถึงพนักงานชั้นฐาน [1] เพื่อชี้ไปที่วัตถุ tbusinessman ที่คุณเพิ่งสร้าง
พนักงาน [2]: = tdocManager.create;
// อ้างถึงพนักงานชั้นฐาน [2] เพื่อชี้ไปที่วัตถุ tDocManager ที่เพิ่งสร้างขึ้น
สำหรับ i: = 0 ถึงความยาว (พนักงาน) -1 ทำ
พนักงาน [i]. startworking;
{จากมุมมองของการใช้ภาษา polymorphism, polymorphism ถูกนำมาใช้โดยการเรียกวิธีการเสมือนจริงโดยตัวชี้ระดับพื้นฐานหรือวัตถุอ้างอิงที่ชี้ไปที่คลาสที่ได้รับ พนักงาน [] หมายถึงอาร์เรย์สำหรับวัตถุคลาสพื้นฐานและสมาชิกชี้ไปที่วัตถุคลาสที่ได้รับที่แตกต่างกันตามลำดับ
จบ;
ลองดู
คุณสามารถพิมพ์รหัสด้านบน (หรือโปรแกรมสาธิต) คอมไพล์และเรียกใช้และคลิกปุ่มเพื่อดูเอฟเฟกต์เวทมนตร์ของ polymorphism
1.2 ความหมายของ polymorphism
ความหมายของการห่อหุ้มและการสืบทอดคือพวกเขาใช้การใช้รหัสซ้ำในขณะที่ความหมายของ polymorphism คือการใช้อินเทอร์เฟซซ้ำ (นิพจน์เดียวกัน) มีความยืดหยุ่น
ตัวอย่างเช่นเพื่อจัดการให้ดีขึ้นโปรแกรมเมอร์จะถูกแบ่งออกเป็นโปรแกรมเมอร์ C ++ และโปรแกรมเมอร์ Delphi -
พนักงาน
/ | / —— ความสัมพันธ์ระหว่างกัน
ผู้จัดการพนักงานขายโปรแกรมเมอร์
/ / —— ความสัมพันธ์ระหว่างประเทศ
โปรแกรมเมอร์ C ++ Programmer Delphi
หลังจากโปรแกรมเมอร์เพิ่มคลาสที่ได้รับสองคลาสของ TCPPProgramer และ TDElphiprogramer วิธีการโทรยังคงไม่เปลี่ยนแปลงและมันก็ยังคงเป็น "พนักงานเริ่มทำงาน" ซึ่งอธิบายด้วยวัตถุ Pascal:
-
SetLength (พนักงาน, enum+2);
พนักงาน [enum]: = tcppprogramer.create;
// สร้างวัตถุ TCPPProgramer และชี้พนักงานอ้างอิงคลาสพื้นฐาน [enum] ไปที่มัน
พนักงาน [enum+1]: = tdelphiprogramer.create;
-
{ภาคเริ่มทำงาน}
สำหรับ i: = 0 ถึงความยาว (พนักงาน) -1 ทำ
พนักงาน [i]. startworking; // มันยังคงเป็นวิธีการโทรเดียวกัน (เพราะอินเทอร์เฟซไม่เปลี่ยนแปลง)
-
1.3 วิธีการใช้ polymorphism ใน Delphi?
เงื่อนไขที่จำเป็นสำหรับการบรรลุความหลากหลายคือการสืบทอดวิธีการเสมือนจริงการผูกมัดแบบไดนามิก (หรือการผูกมัดความล่าช้า)
1.3.1 มรดก
การสืบทอดหมายถึง "Ako (ชนิดหนึ่งคือ A)" ความสัมพันธ์ระหว่างชั้นเรียนเช่นโปรแกรมเมอร์ "เป็น" พนักงานซึ่งบ่งบอกถึงความสัมพันธ์การสืบทอด ใน Delphi ได้รับการสนับสนุนการสืบทอดเพียงครั้งเดียว (ไม่มีการพิจารณาการสืบทอดหลายครั้งโดยอินเทอร์เฟซ) โดยวัตถุคลาสที่ได้รับ (หรือในทางกลับกัน)
คำใบ้
ใน UML:
Ako: ความสัมพันธ์ในการสืบทอดวิธีการ
Apo: ส่วนหนึ่งของความสัมพันธ์แบบผสมผสาน
ISA: ISA แสดงถึงความสัมพันธ์ระหว่างวัตถุและคลาสที่เป็นของมัน
1.3.2 วิธีการเสมือนจริงวิธีการแบบไดนามิกและวิธีการนามธรรม, VMT/DMT, การเชื่อมแบบคงที่และการเชื่อมโยงแบบไดนามิก
สำหรับทุกวิธีไม่มีร่องรอยในวัตถุ ตัวชี้วิธีการ (ที่อยู่รายการ) จะถูกเก็บไว้ในชั้นเรียนในขณะที่รหัสจริงจะถูกเก็บไว้ในเซ็กเมนต์รหัส สำหรับวิธีการคงที่ (วิธีการที่ไม่ใช่เสมือน) คอมไพเลอร์จะกำหนดที่อยู่รายการของวิธีการตามประเภทการอ้างอิงของวัตถุโดยตรงซึ่งเรียกว่าการผูกมัดแบบคงที่สำหรับวิธีการเสมือนจริง คอมไพเลอร์ไม่สามารถกำหนดคลาสจริงที่เป็นของมันได้ดังนั้นที่อยู่รายการของวิธีการสามารถกำหนดได้ผ่านที่อยู่ตาราง VMT (เช่นสี่ไบต์แรกของวัตถุ) ในระหว่างการรันไทม์ การระดมทุนล่าช้า)
วิธีเสมือนจริง
วิธีการเสมือนจริงแสดงถึงวิธีการที่สามารถแทนที่ได้ นอกเหนือจากการจัดเก็บตัวชี้วิธีการเสมือนจริงของตัวเองคลาสยังเก็บตัวชี้วิธีการเสมือนจริงของคลาสฐานทั้งหมด
วิธีการประกาศ:
ชื่อวิธีการ;
สิ่งนี้เทียบเท่ากับการบอกคอมไพเลอร์ Delphi:
วิธีนี้สามารถมากเกินไปในคลาสที่ได้รับและวิธีการเสมือนจริงจะยังคงอยู่หลังจากการโอเวอร์โหลด
อย่ากำหนดที่อยู่รายการของวิธีการในช่วงระยะเวลาการรวบรวม ในระหว่างการรันไทม์ที่อยู่รายการของวิธีการจะถูกกำหนดผ่านการเชื่อมโยงแบบไดนามิก
ให้การใช้งานเริ่มต้นในคลาสฐาน
วิธีการแบบไดนามิก
วิธีการแบบไดนามิกและวิธีการเสมือนจริงนั้นเหมือนกัน แต่นี่เป็นสิ่งที่โปร่งใสอย่างสมบูรณ์สำหรับผู้ใช้
วิธีการประกาศ:
ชื่อขั้นตอน; Dynamic;
วิธีนามธรรม
วิธีการเสมือนพิเศษพิเศษซึ่งไม่จำเป็นต้องจัดเตรียมการใช้งานเริ่มต้นในคลาสพื้นฐานนั้นใช้สำหรับอินเทอร์เฟซการโทรซึ่งเทียบเท่ากับฟังก์ชั่นเสมือนจริงใน C ++ คลาสที่มีวิธีการนามธรรมเรียกว่าคลาสนามธรรม
วิธีการประกาศ:
ชื่อขั้นตอน; เสมือน; บทคัดย่อ;
VMT/DMT
ใน Delphi ตารางวิธีการเสมือนจริง (VMT) ไม่ได้เป็นจริง วิธีการเสมือนจริงของคลาสฐาน "ที่อยู่รายการ VMT" ที่เก็บไว้ในสี่ไบต์แรกของวัตถุนั้นเป็นที่อยู่ของคลาสที่เป็นของ (ดูโปรแกรมสาธิต) ด้วยคลาสจริงที่อยู่วิธีการเสมือนสามารถพบได้
OBJ (ชื่อวัตถุ) คลาสที่วัตถุจริงเป็นของ
ที่อยู่รายการ VMT
สมาชิกข้อมูล
ที่อยู่รายการ VMT ของตารางวิธีการเสมือนคลาสคลาส
ข้อมูลแม่แบบสมาชิกข้อมูล
วิธีการคงที่ ฯลฯ
วิธีการเสมือนจริง (VMT)
วิธีการไดนามิก (DMT)
รูปที่ 3 ความสัมพันธ์ระหว่างชื่อวัตถุวัตถุและคลาส
DMT คล้ายกับ VMT และยังเป็นแนวคิดเชิงตรรกะ ไม่เร็วเท่ากับวิธีการเสมือนจริง
อ้างตัวอย่างข้างต้นเพื่ออธิบาย:
พนักงาน [i]. Startworking;
พนักงาน [i] เป็นวัตถุอ้างอิงของ Templeeyee คลาสพื้นฐาน ดังนั้นวัตถุที่เกิดขึ้นจริงจึงไม่สามารถรู้ได้ในระหว่างการรวบรวมดังนั้นจึงไม่สามารถกำหนดที่อยู่วิธีการได้ ในช่วงระยะเวลาการวิ่งฉันรู้ว่า "ใบหน้าที่แท้จริงของ Lushan" ของวัตถุ ฟังก์ชั่นที่เรียกว่านั่นคือความหลากหลายของความหลากหลาย
1.3.3 โอเวอร์โหลดและ polymorphism
ชาวเน็ตหลายคนเชื่อว่าฟังก์ชั่นโอเวอร์โหลดนั้นเป็นความหลากหลายเช่นกัน แต่ก็ไม่ใช่ สำหรับ "การดำเนินการที่แตกต่างกัน" การโอเวอร์โหลดไม่สามารถให้วิธีการโทรเดียวกันได้ หลักฐานของการใช้ polymorphism เป็นการแสดงออกเดียวกัน! ตัวอย่างเช่นพนักงาน [i]. startworing การโทรมากเกินไปมีพารามิเตอร์หรือประเภทพารามิเตอร์ที่แตกต่างกัน การโอเวอร์โหลดเป็นเพียงกลไกทางภาษาและยังมีการโอเวอร์โหลดใน C แต่ C ไม่มีความหลากหลายและ C ไม่ใช่ภาษาการเขียนโปรแกรมเชิงวัตถุ เว้นแต่ว่าฟังก์ชั่นการโอเวอร์โหลดเป็นวิธีการเสมือนจริงคอมไพเลอร์สามารถกำหนดที่อยู่รายการของฟังก์ชั่นตามประเภทพารามิเตอร์หรือการผูกคงที่! อ้างถึงพ่อของ C ++ "อย่าโง่ถ้ามันไม่ใช่การเชื่อมโยงแบบไดนามิกมันไม่ใช่ polymorphism"
1.4 การอภิปรายเกี่ยวกับสปีชีส์ polymorphic
1.4.1 polymorphism สองระดับ
ระดับวัตถุ: ใช้ตัวชี้คลาสฐาน/การอ้างอิงเพื่อชี้ไปที่วัตถุคลาสที่ได้รับและการเรียกวิธีการเสมือน (หรือวิธีการแบบไดนามิกวิธีนามธรรม) ซึ่งเป็นวิธีที่ใช้กันมากที่สุด
ระดับคลาส: ใช้การอ้างอิงคลาส (การอ้างอิงถึงคลาสมากกว่าวัตถุ) เพื่อชี้ไปที่คลาสที่ได้รับวิธีการเรียกวิธีการคลาสเสมือน (หรือวิธีการคลาสแบบไดนามิก, วิธีการคลาสนามธรรม) และใช้กันทั่วไปใน polymorphisms ที่สร้างขึ้นโดยวัตถุ (เพราะคอนสตรัคเตอร์เป็น วิธีการประเภท "สำหรับพิเศษ" โปรดดูการวิเคราะห์งานอื่น ๆ ของฉัน "การวิเคราะห์โครงสร้างและการทำลายล้างใน Delphi", ส่วนที่ 2.1)
คำใบ้
การอ้างอิงคลาสเป็นตัวแปรอ้างอิงของคลาสเองไม่ใช่คลาสหรือการอ้างอิงวัตถุ เช่นเดียวกับชื่อวัตถุแสดงถึงการอ้างอิงวัตถุชื่อคลาสแสดงถึงการอ้างอิงคลาสเนื่องจากใน Delphi คลาสจะถูกประมวลผลเป็นวัตถุ ประเภทการอ้างอิงคลาสคือประเภทของการอ้างอิงคลาสและวิธีการประกาศของประเภทอ้างอิงคลาส:
ชื่อประเภทอ้างอิงคลาส = คลาสของชื่อคลาส
เราสามารถเห็นการประกาศอ้างอิงชั้นเรียนจำนวนมากในซอร์สโค้ด VCL เช่น:
tclass = คลาสของ tobject;
tComponentClass = คลาสของ tComponent;
tControlClass = คลาสของ tControl;
สังเกต
ในเมธอดคลาสตัวเองโดยนัยในวิธีการอ้างอิงคลาสไม่ใช่การอ้างอิงวัตถุ
1.4.2 polymorphism ที่ไม่ปลอดภัย
Polymorphism สามารถนำไปใช้ได้โดยใช้พอยน์เตอร์คลาสที่ได้รับ/การอ้างอิงไปยังวัตถุคลาสพื้นฐาน!
ขั้นตอน TFORM1.BTNBADPOLYCLICK (ผู้ส่ง: TOBJECT);
วาจา
CPPProgramer: TCPPProgramer; // กำหนดอ้างอิงโปรแกรมเมอร์ CPP ซึ่งอ้างอิงถึงคลาสที่ได้รับ!
เริ่ม
{*****************************คำแถลง******************* ****************
ความหลากหลายที่นำมาใช้กับพอยน์เตอร์คลาสที่ได้รับ/การอ้างอิงไปยังวัตถุคลาสพื้นฐาน มันเป็น polymorphism ทางพยาธิวิทยา!
วิธีการ polymorphic นี้เป็นเหมือนสิ่งเล็ก ๆ (วัตถุคลาสพื้นฐาน) ที่ปกคลุมไปด้วยวิธีการที่ทรงพลัง
การปรากฏตัวของผลิตภัณฑ์ (การอ้างอิงคลาสที่ได้รับ) จึงนำปัจจัยความไม่มั่นคงที่อาจเกิดขึ้นมากมาย (เช่นข้อยกเว้นการเข้าถึง) ดังนั้น
แทบไม่มีค่า "ไฟล์" ตัวอย่างมีวัตถุประสงค์เพื่อแสดงให้เห็นถึงลักษณะของความหลากหลายใน Delphi ลักษณะของ polymorphism: ใช้ตัวชี้/คลาสพื้นฐาน) ตัวชี้/การอ้างอิงเพื่อใช้งานวัตถุตามวัตถุจริงในระหว่างการรันไทม์เพื่อดำเนินการที่แตกต่างกัน วิธีการหรือคำสั่งที่ชัดเจนยิ่งขึ้น: วัตถุนั้นตัดสินใจเลือกวิธีการทำงานของตัวเองเท่านั้น วัตถุ สิ่งนี้ช่วยให้การแยกอินเทอร์เฟซและการใช้งานทำให้อินเทอร์เฟซนำมาใช้ซ้ำได้
******************************************************** ******* *******************************}
CPPProgramer: = TCPPProgramer (tprogramer.create);
{เพื่อให้บรรลุความหลากหลายทางพยาธิวิทยานี้การอ้างอิงวัตถุจะถูกส่งไปยังประเภท TCPPProgramer
ดังนั้นการหลบหนีการตรวจสอบของคอมไพเลอร์}
CPPProgramer.Startworking;
{tprogramer.startworking เรียกว่าแทน tcppprogramer.startworking
นี่คือ polymorphism ที่นำมาใช้กับพอยน์เตอร์คลาสที่ได้รับ/การอ้างอิงไปยังวัตถุคลาสพื้นฐาน -
cppprogramer.free;
CPPProgramer: = TCPPProgramer (tDocManager.create);
CPPProgramer.Startworking;
{การโทรคือ tdocManager.startworking
นี่คือ polymorphism ที่นำมาใช้กับพอยน์เตอร์คลาสที่ได้รับ/การอ้างอิงไปยังวัตถุคลาสพื้นฐาน วิธีนี้ไม่ปลอดภัยอย่างยิ่ง
และไม่จำเป็น}
cppprogramer.free;
จบ;
ลองดู
เพื่อให้ได้รับความเข้าใจประเภทนี้เกี่ยวกับความหลากหลายของความหลากหลายแนะนำให้ลองใช้ ? ข้อยกเว้นการเข้าถึงจะเกิดขึ้นภายใต้สถานการณ์ใด (ดูโปรแกรมสาธิต)
2 แอปพลิเคชันของ polymorphism ใน VCL
2.1 วิธีการก่อสร้างและการทำลายล้าง
ความหลากหลายของวิธีการก่อสร้าง
เนื่องจากคอนสตรัคเตอร์ถือได้ว่าเป็นวิธีการเรียน "พิเศษ" คลาสที่ได้รับทั้งหมดหลังจาก TComponent ถูกกำหนดใหม่เป็นวิธีการชั้นเรียนเสมือนจริงดังนั้นเพื่อตระหนักถึงความหลากหลายของตัวสร้างคุณต้องใช้การอ้างอิงคลาส ในแต่ละไฟล์โครงการมีรหัสคล้ายกับต่อไปนี้:
application.createform (tform1, form1);
คำจำกัดความของวิธีการ:
procedure tapplication.createform (instanceclass: tComponentClass; การอ้างอิง var);
var // instanceclass เป็นข้อมูลอ้างอิงคลาส
อินสแตนซ์: tComponent;
เริ่ม
อินสแตนซ์: = tComponent (instanceclass.NewInstance);
{Newinstance Method Declaration: ฟังก์ชั่นคลาส Newinstance: Tobject; Instanceclass เป็นข้อมูลอ้างอิงคลาสที่ใช้ polymorphism ระดับคลาสดังนั้นจึงตระหนักถึงการใช้อินเทอร์เฟซซ้ำสำหรับการสร้างส่วนประกอบ}
tComponent (อ้างอิง): = อินสแตนซ์;
พยายาม
instance.create (self); // เรียกตัวสร้างเพื่อเริ่มต้นมัน
ยกเว้น
tComponent (อ้างอิง): = nil; // กำจัดตัวชี้ "ป่า"! ดี
ยก;
จบ;
{ถ้าหน้าต่างที่สร้างขึ้นและยังไม่มีรูปแบบหลักตั้งค่าแบบฟอร์มที่สร้างขึ้นเพียงแค่รูปแบบหลัก}
ถ้า (fmainform = nil) และ (อินสแตนซ์คือ tform) จากนั้น
เริ่ม
tform (อินสแตนซ์) .handleneeded;
fmainform: = tform (อินสแตนซ์); // ตั้งค่าฟอร์มหลัก
{อันที่จริงการตั้งค่าแบบฟอร์มหลักในตัวเลือกโครงการ (ตัวเลือก Project->) เป็นคำสั่งฟอร์มที่สอดคล้องกันในไฟล์โครงการก่อนที่คำสั่งการสร้างแบบฟอร์มทั้งหมด -
จบ;
จบ;
2) สำหรับความหลากหลายของวิธีการทำลายล้างโปรดดู "การวิเคราะห์โครงสร้างและการทำลายล้างใน Delphi" ส่วนที่ 3.3
2.2 tstrings
การประมวลผลสตริงอาร์เรย์เป็นเรื่องธรรมดามากในการควบคุม Delphi โดยปกติจะมีแอตทริบิวต์บางรายการซึ่งสะดวกโดยเฉพาะอย่างยิ่งสำหรับเราที่จะใช้ (เพราะพวกเขาทั้งหมดใช้อินเทอร์เฟซเดียวกัน) ขอบคุณการออกแบบสถาปัตยกรรมสตริงอาร์เรย์ใน Delphi นี่คือการออกแบบที่ประสบความสำเร็จ
เนื่องจากการควบคุมจำนวนมากใช้อาร์เรย์สตริงเช่น ComboBox, TStringGrid ฯลฯ แต่อาร์เรย์สตริงในแต่ละตัวควบคุมจะแตกต่างกัน Delphi นามธรรมสตริงอาร์เรย์ดังนั้นคลาสที่เกี่ยวข้องจำนวนมากจึงปรากฏขึ้น TSTRINGS คลาสพื้นฐานจัดเตรียมอินเทอร์เฟซสำหรับการโทรต่าง ๆ และการใช้งานที่เฉพาะเจาะจงสามารถนำมาใช้ทั้งหมดจากคลาสที่ได้รับ
ลองมาดูคำจำกัดความของวิธีการทั่วไปของคลาส TSTRINGS คลาสพื้นฐาน (ดูคลาส UNIS LINE 442):
tStrings = class (tpersistent)
ได้รับการคุ้มครอง
-
ฟังก์ชั่นรับ (ดัชนี: จำนวนเต็ม): สตริง;
ขั้นตอนการใส่ (ดัชนี: จำนวนเต็ม; const s: string);
ฟังก์ชั่น getCount: จำนวนเต็ม;
-
สาธารณะ
ฟังก์ชั่นเพิ่ม (สตริง): จำนวนเต็ม;
{เพิ่มสตริง S ที่ส่วนท้ายของรายการสตริง}
Addstrings ขั้นตอน (Strings: TSTRINGS);
{เพิ่มสตริงไปที่ส่วนท้ายของรายการสตริง}
ขั้นตอนการแทรก (ดัชนี: จำนวนเต็ม; const s: สตริง);
{วิธีนามธรรม, ใส่สตริงใหม่ s ที่ตำแหน่งดัชนี}
ขั้นตอนที่ชัดเจน;
{ล้างสตริงทั้งหมด}
ขั้นตอนการลบ (ดัชนี: จำนวนเต็ม);
{ลบสตริงในสถานที่ที่แน่นอน}
ฟังก์ชั่นดัชนี (const s: string): จำนวนเต็ม;
{รับตำแหน่งของ S ในรายการสตริง}
ฟังก์ชั่น indexofname (ชื่อ const: string): จำนวนเต็ม;
{ส่งคืนตำแหน่งของสตริงแรกด้วยชื่อฟอร์ม = ค่าด้วยส่วนชื่อที่ระบุ}
ฟังก์ชั่น indexofobject (aoBject: toBject): จำนวนเต็ม;
{รับตำแหน่งของวัตถุที่มีวัตถุชื่อ AObject: ในรายการสตริง}
Procedure LoadFromFile (ชื่อไฟล์ const: String);
{เติมรายการด้วยบรรทัดของข้อความในไฟล์ที่ระบุ}
ขั้นตอนการโหลดจากสตรีม (สตรีม: TStream);
{เติมรายการด้วยบรรทัดของข้อความที่อ่านจากสตรีม}
ขั้นตอน Savetostream (สตรีม: TStream);
{เขียนค่าของคุณสมบัติข้อความไปยังวัตถุสตรีม}
สตริงคุณสมบัติ [ดัชนี: จำนวนเต็ม]: การอ่านสตริงรับเขียนลง;
{อ้างอิงสตริงในรายการโดยตำแหน่งของพวกเขา}
ค่าคุณสมบัติ [ชื่อ const: string]: string read getValue เขียน setValue;
{แสดงส่วนค่าของสตริงที่เกี่ยวข้องกับชื่อที่กำหนดบนสตริงที่มีชื่อฟอร์ม = ค่า}
-
จบ;
จากคำจำกัดความของ TSTRINGS จะเห็นได้ว่าวิธีการที่ได้รับการปกป้องและสาธารณะส่วนใหญ่เป็นวิธีการเสมือนจริงหรือวิธีการนามธรรม (โปรดเพิ่มบางส่วน TSTRINGLIST-> TSTRINGGRIDSTRING)
2.3 คนอื่น ๆ (โปรดเพิ่มวิญญาณ)
หากคุณยังไม่เข้าใจ polymorphism โปรดจดจำสาระสำคัญของ polymorphism:
"การแสดงออกเดียวกันการดำเนินการที่แตกต่างกัน" (มันง่ายมาก)
จากมุมมองของการใช้ภาษา OOP ความหลากหลายคือการใช้ตัวชี้/การอ้างอิงของคลาสฐานเพื่อใช้งานวัตถุ (คลาสที่ได้รับ) และดำเนินการวิธีการที่แตกต่างกันตามวัตถุจริงในช่วงระยะเวลาการรัน; คำแถลงที่ชัดเจนยิ่งขึ้น: วัตถุตัดสินใจวิธีการทำงานของตัวเอง ตัวเอง สิ่งนี้ช่วยให้การแยกอินเทอร์เฟซและการใช้งานทำให้อินเทอร์เฟซนำมาใช้ซ้ำได้
ในความเป็นจริง polymorphism นั้นง่าย! ดังนั้นคุณควรให้ความสนใจกับการใช้ polymorphism อย่างไร? นี่คือคำแนะนำสองข้อของฉัน:
วิเคราะห์ตรรกะทางธุรกิจจากนั้นสิ่งที่เกี่ยวข้องกับนามธรรมลงใน "วัตถุ" จากนั้นห่อหุ้มตรรกะทางธุรกิจโดยใช้วิธีการวัตถุ ประกาศการดำเนินการบางอย่างด้วย polymorphism เป็นวิธีการเสมือนจริงในคลาสฐานและประกาศว่าพวกเขาเป็นวิธีการนามธรรมเสมือนจริงสำหรับผู้ที่ไม่จำเป็นต้องใช้ในคลาสฐานและจากนั้นมากเกินไปในชั้นเรียนที่ได้รับ /พอยน์เตอร์ของคลาสฐานเมื่อใช้ซึ่งตระหนักถึงความหลากหลายในโลกแห่งความเป็นจริง โปรดจำไว้ว่าไม่ให้บรรลุความหลากหลายเพื่อประโยชน์ของความหลากหลาย
เนื่องจากมีความสัมพันธ์ "การมีเพศสัมพันธ์" ตามธรรมชาติระหว่างคลาสพื้นฐานและคลาสที่ได้รับการปรับเปลี่ยนคลาสฐานจะนำไปสู่ "การเข้าถึงร่างกายทั้งหมด" ซึ่งจะลำบากมาก! ดังนั้นเราต้องพยายามทำให้การใช้งานของคลาสฐานอ่อนแอลงออกแบบเป็น "คลาสนามธรรม" หากจำเป็นและตรวจสอบให้แน่ใจว่ามีการเชื่อมต่อที่มั่นคง
คำถามที่เกี่ยวข้อง
พูดคุยเกี่ยวกับความหลากหลายของ Delphi: http://www.delphhibbs.com/delphibbs/dispq.asp?lid=1753965
เกี่ยวกับ polymorphism: http://www.delphhibbs.com/delphibbs/dispq.asp?lid=1854895
polymorphism คืออะไร? การใช้งานในการเขียนโปรแกรมรายวันคืออะไร? http://www.delphibbs.com/delphibbs/dispq.asp?lid=960465
อะไรคือความแตกต่างระหว่างการโอเวอร์โหลดและการแทนที่? http://www.delphibs.com/delphibs/dispq.asp?lid=296739
ออกว่าตัวชี้ของคลาสที่ได้รับชี้ไปที่วัตถุคลาสพื้นฐาน http://www.delphibs.com/delphibs/dispq.asp?lid=2104106
(คำถามสุดท้ายถูกกล่าวถึงใน Delphibbs เมื่อฉันศึกษา polymorphism อย่างลึกซึ้งซึ่งทำให้เกิดการสนทนาที่ร้อนแรงฉันขอแนะนำให้คุณดู)