เหตุใดกรอบงาน. NET จึงไม่มีแนวคิดของคลาสเป็นประเภทเฟิร์สคลาส


20

เป็นที่รู้จักกันดีสำหรับผู้ที่คุ้นเคยกับประวัติที่ C # และ. NET Framework เริ่มต้นจากการที่ "Delphi เขียนใหม่เพื่อให้รู้สึกเหมือน Java" ได้รับการออกแบบโดยหัวหน้าผู้พัฒนาที่อยู่เบื้องหลัง Delphi, Anders Hejlsberg สิ่งต่าง ๆ ได้เบี่ยงเบนไปเล็กน้อยตั้งแต่นั้นมา แต่ในช่วงต้นของความคล้ายคลึงกันได้ชัดเจนว่ามีการเก็งกำไรร้ายแรงบางอย่างที่. NET เป็นผลิตภัณฑ์ดั้งเดิมของ Borland

แต่ฉันได้ดูบางสิ่ง. NET เมื่อเร็ว ๆ นี้และหนึ่งในคุณสมบัติที่น่าสนใจและมีประโยชน์ที่สุดจาก Delphi ดูเหมือนจะหายไปโดยสิ้นเชิง: แนวคิดของคลาสเป็นประเภทข้อมูลชั้นหนึ่ง สำหรับผู้ที่ไม่คุ้นเคยกับมันประเภทTClassแสดงถึงการอ้างอิงถึงระดับคล้ายกับTypeประเภทใน. NET แต่ที่. NET ใช้Typeในการสะท้อนเดลฟีใช้TClassเป็นส่วนสำคัญในตัวของภาษา มันช่วยให้สำนวนที่เป็นประโยชน์ต่าง ๆ ที่ไม่มีและไม่มีอยู่จริงเช่นตัวแปรคลาสย่อยและวิธีคลาสเสมือน

ทุกภาษา OO มีวิธีการเสมือนซึ่งคลาสที่แตกต่างกันใช้แนวคิดพื้นฐานเดียวกันของวิธีการในวิธีที่ต่างกันและจากนั้นวิธีการที่เหมาะสมจะได้รับการเรียกใช้ที่รันไทม์ตามชนิดที่แท้จริงของอินสแตนซ์วัตถุที่เรียกว่า Delphi ขยายแนวคิดนี้ไปยังคลาส: ถ้าคุณมีการอ้างอิง TClass ที่กำหนดเป็นคลาสย่อยเฉพาะ (เช่นclass of TMyClassหมายความว่าตัวแปรสามารถรับการอ้างอิงคลาสใด ๆ ที่สืบทอดมาTMyClassแต่ไม่ใช่สิ่งใดนอก heirarchy) ที่มีเมธอดเสมือนของคลาสขอบเขต มันสามารถถูกเรียกโดยไม่มีอินสแตนซ์โดยใช้ชนิดของคลาสที่แท้จริง การใช้รูปแบบนี้กับตัวสร้างทำให้การใช้งานเป็นเรื่องเล็กน้อยสำหรับโรงงาน

ดูเหมือนจะไม่มีอะไรเทียบเท่าใน. NET มีประโยชน์เท่ากับการอ้างอิงคลาส (และโดยเฉพาะอย่างยิ่งคอนสตรัคเตอร์เสมือนจริงและเมธอดคลาสเสมือนอื่น ๆ !) มีใครเคยพูดอะไรเกี่ยวกับสาเหตุที่พวกเขาถูกทิ้ง?

ตัวอย่างเฉพาะ

Deserialization แบบฟอร์ม

Delphi VCL บันทึกแบบฟอร์มในDFMรูปแบบ DSL สำหรับอธิบายลำดับชั้นองค์ประกอบ เมื่อเครื่องอ่านฟอร์มแยกวิเคราะห์ข้อมูล DFM เครื่องจะอ่านข้ามวัตถุที่อธิบายดังนี้:

object Name: ClassName
   property = value
   property = value
   ...
   object SubObjectName: ClassName
      ...
   end
end

สิ่งที่น่าสนใจที่นี่คือClassNameส่วนหนึ่ง แต่ละคลาสคอมโพเนนต์จะรีจิสเตอร์TClassกับระบบการสตรีมคอมโพเนนต์ในinitializationเวลานั้น (คิดว่าตัวสร้างสแตติกเท่านั้นแตกต่างกันเล็กน้อยรับประกันว่าจะเกิดขึ้นทันทีเมื่อเริ่มต้น) สิ่งนี้จะลงทะเบียนแต่ละคลาสในสตริง -> TClass hashmap ด้วยชื่อคลาสเป็นคีย์

แต่ละองค์ประกอบลงมาจากที่มีคอนสตรัคเสมือนที่ใช้อาร์กิวเมนต์เดียวTComponent Owner: TComponentส่วนประกอบใด ๆ สามารถแทนที่ตัวสร้างนี้เพื่อจัดเตรียมการเริ่มต้นของตัวเอง เมื่อผู้อ่าน DFM อ่านชื่อคลาสจะค้นหาชื่อใน hashmap ข้างต้นและดึงการอ้างอิงคลาสที่สอดคล้องกัน (หรือยกข้อยกเว้นหากไม่มีอยู่) จากนั้นเรียกตัวสร้างเสมือนของ TComponent ซึ่งเป็นที่รู้จักกันดี เนื่องจากฟังก์ชั่นการลงทะเบียนใช้การอ้างอิงระดับที่จำเป็นในการสืบทอดจาก TComponent และคุณจะจบลงด้วยวัตถุประเภทที่เหมาะสม

หากขาดสิ่งนี้ WinForms ที่เทียบเท่ากันก็คือ ... ความยุ่งเหยิงที่ยิ่งใหญ่ที่จะนำมันอย่างตรงไปตรงมาซึ่งต้องการภาษา. NET ใหม่ใด ๆ มันค่อนข้างน่าตกใจเมื่อคุณคิดถึงมัน เนื่องจากจุดรวมของการมี CLR คือการให้หลายภาษาใช้โครงสร้างพื้นฐานพื้นฐานเดียวกันระบบ DFM ในสไตล์จึงเหมาะสมเป็นอย่างยิ่ง

ขยาย

คลาสตัวจัดการรูปภาพที่ฉันเขียนสามารถให้กับแหล่งข้อมูล (เช่นพา ธ ไปยังไฟล์รูปภาพของคุณ) จากนั้นโหลดวัตถุรูปภาพใหม่โดยอัตโนมัติหากคุณพยายามเรียกชื่อที่ไม่ได้อยู่ในคอลเลกชัน แต่มีอยู่ในแหล่งข้อมูล มันมีตัวแปรคลาสที่พิมพ์เป็นclass ofคลาสอิมเมจฐานแสดงถึงคลาสของวัตถุใหม่ใด ๆ ที่จะสร้าง มันมาพร้อมกับค่าเริ่มต้น แต่มีบางจุดเมื่อสร้างภาพใหม่โดยมีวัตถุประสงค์พิเศษว่าควรตั้งค่ารูปภาพด้วยวิธีต่างๆ (สร้างโดยไม่มีช่องอัลฟาเรียกข้อมูลเมตาพิเศษจากไฟล์ PNG เพื่อระบุขนาดสไปรต์ ฯลฯ )

สิ่งนี้สามารถทำได้โดยการเขียนรหัสการกำหนดค่าจำนวนมากและส่งตัวเลือกพิเศษไปยังวิธีการทั้งหมดที่อาจสิ้นสุดการสร้างวัตถุใหม่ ... หรือคุณสามารถสร้างคลาสย่อยของคลาสอิมเมจพื้นฐานที่แทนที่เมธอดเสมือนที่ ด้านที่มีปัญหาได้รับการกำหนดค่าจากนั้นใช้การลอง / ในที่สุดบล็อกเพื่อแทนที่คุณสมบัติ "คลาสเริ่มต้น" ชั่วคราวตามที่ต้องการแล้วจึงกู้คืน การทำมันด้วยตัวแปรอ้างอิงระดับนั้นง่ายกว่ามากและไม่ใช่สิ่งที่สามารถทำได้ด้วยยาชื่อสามัญแทน


3
อาจจะเป็นเพราะมันไม่ได้มีคุณสมบัติที่มีความสำคัญสูงที่พอดีกับงบประมาณ C # ของทีม
Doval

3
คุณสามารถให้ตัวอย่างที่เป็นรูปธรรมหนึ่งหรือสองอันที่มีTClassประโยชน์ด้วยรหัสตัวอย่างบ้างไหม? ในการวิจัยทางอินเทอร์เน็ตคร่าวๆของฉันเกี่ยวกับTClassฉันพบว่าTClassสามารถส่งผ่านเป็นพารามิเตอร์ สิ่งนี้ทำใน. NET โดยใช้ Generics เมธอดจากโรงงานถูกทำเครื่องหมายstaticใน. NET และไม่ต้องการอินสแตนซ์ของคลาสในการดำเนินการ
Robert Harvey

7
@RobertHarvey: สำหรับฉันโดยส่วนตัวแล้ว C # เริ่มมีเหตุผลมากขึ้นเมื่อฉันหยุดมองมันในขณะที่ Java / C ++ โหลดซ้ำและเริ่มรักษามันเป็น Modula-2 กับวัตถุ เหมือนกับ Java: ทุกคนบอกว่ามันได้รับอิทธิพลจาก C ++ แต่นั่นไม่เป็นความจริง อิทธิพลหลักของมันคือ Objective-C (และสมอลล์ทอล์คผ่านทางนั้น) และ Java จะทำให้มากรู้สึกมากขึ้นเมื่อคุณรักษามันเป็นสมอลล์ทอล์คกับชนิดแทน C ++ กับ GC
Jörg W Mittag

3
@RobertHarvey: TClassเป็นคุณสมบัติภาษาพื้นฐานที่ต้องการการสนับสนุนคอมไพเลอร์ คุณไม่สามารถ "เขียนของคุณเอง" โดยไม่ต้องเขียนภาษาของคุณเองและสำหรับ. NET แม้จะไม่เพียงพอเพราะรูปแบบวัตถุถูกกำหนดโดย CLR ไม่ใช่ด้วยภาษาแต่ละภาษา เป็นสิ่งที่แท้จริงต้องเป็นส่วนหนึ่งของ. NET Framework หรือไม่สามารถอยู่ได้
Mason Wheeler

4
ก่อนอื่นผมสามารถพูดได้อย่างมั่นใจว่า. NET ไม่ใช่ผลิตภัณฑ์ "Borland" ฉันจะรู้สิ่งนี้ได้อย่างไร ฉันเป็นส่วนหนึ่งของทีมแกนหลักดั้งเดิมที่พัฒนา Delphi ฉันทำงานอย่างใกล้ชิดกับ Anders, Chuck, Gary และคนอื่น ๆ แน่นอนฉันมั่นใจว่าคุณรู้เรื่องนี้ สำหรับการมีอยู่ของการอ้างอิงคลาส (เป็น TClass และการสร้างที่คล้ายกันเรียกว่า) ใน. NET มีแนวโน้มที่จะถือว่าไม่จำเป็นเนื่องจากการมีอยู่ของข้อมูลประเภทที่สามารถเข้าถึงได้ในเวลาทำงาน Delphi มีข้อมูลประเภทที่น้อยกว่ามากในการเริ่มต้นและการอ้างอิงระดับมีการประนีประนอม
อัลเลนบาวเออร์

คำตอบ:


5

.NET (the CLR) เป็นรุ่นที่สามของ Microsoft Component Object Model (COM) ซึ่งในยุคแรก ๆ เรียกว่า "COM + runtime" Microsoft Visual Basic และตลาดการควบคุม COM / ActiveX มีอิทธิพลต่อตัวเลือกความเข้ากันได้ทางสถาปัตยกรรม CLR มากกว่า Borland Delphi (ความจริงที่ว่า Delphi ได้นำการควบคุม ActiveX มาใช้นั้นช่วยให้ระบบนิเวศ ActiveX เติบโตขึ้นอย่างแน่นอน แต่ COM / ActiveX มีอยู่ก่อน Delphi)

สถาปัตยกรรมของ COM ทำงานใน C (ไม่ใช่ C ++) และมุ่งเน้นไปที่อินเตอร์เฟสมากกว่าคลาส นอกจากนี้ยังสนับสนุนองค์ประกอบของวัตถุซึ่งหมายความว่าในความเป็นจริงวัตถุ COM อาจประกอบด้วยวัตถุที่แตกต่างกันหลายตัวโดยมีอินเตอร์เฟส IUnknown เชื่อมโยงเข้าด้วยกัน แต่ IUnknown ไม่มีบทบาทในการสร้างวัตถุ COM ซึ่งได้รับการออกแบบให้ไม่ขึ้นกับภาษามากที่สุด การสร้างวัตถุได้รับการจัดการโดย IClassFactory และการสะท้อนกลับโดย ITypeLibrary และอินเตอร์เฟสที่เกี่ยวข้อง การแยกข้อกังวลนี้ไม่ขึ้นอยู่กับภาษาที่ใช้งานและคุณลักษณะของแต่ละอินเตอร์เฟส COM หลักถูกเก็บรักษาไว้น้อยที่สุดและเป็นมุมฉาก

ดังนั้นเนื่องจากความนิยมของตัวควบคุม COM และ ActiveX สถาปัตยกรรม. NET จึงถูกสร้างขึ้นเพื่อรองรับบน COM IUnknown, IClassFactory และ ITypeLibrary ใน COM อินเทอร์เฟซเหล่านี้ไม่จำเป็นต้องอยู่บนวัตถุเดียวกันดังนั้นการรวมกันของเหล่านี้จึงไม่สมเหตุสมผล

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.