การสร้างคลาสที่มีวัตถุประสงค์เพื่อแปลงเป็นคลาสอื่นโดยปริยายหรือไม่?


10

ลองนึกภาพสถานการณ์ที่เรากำลังใช้ห้องสมุดที่อนุญาตให้คุณสร้างCircleวัตถุที่คุณสามารถระบุรัศมีและศูนย์กลางของวงกลมเพื่อกำหนด อย่างไรก็ตามด้วยเหตุผลบางอย่างมันยังใช้flavourพารามิเตอร์ที่จำเป็น ตอนนี้สมมติว่าฉันจำเป็นต้องใช้Circleในแอพของฉันเอง แต่สำหรับวัตถุประสงค์ของแอพของฉันฉันสามารถกำหนดรสชาติให้เป็นFlavours.Cardboardทุกครั้ง

ในการ "แก้ปัญหา" สิ่งนี้ฉันสร้างCircleคลาสของตัวเองในเนมสเปซที่ต่างกันซึ่งใช้radiusและcenterเป็นพารามิเตอร์เท่านั้น แต่มีตัวแปลงโดยนัยไปยังCircleคลาสของไลบรารีภายนอกซึ่งเพิ่งสร้างCircle(this.radius, this.center, Flavours.Cardboard)วัตถุ ดังนั้นทุกที่ที่ฉันต้องการประเภทอื่นCircleฉันจะให้การแปลงอัตโนมัติเกิดขึ้น

อะไรคือผลของการสร้างชั้นเรียนดังกล่าว? มีวิธีแก้ปัญหาที่ดีกว่านี้ไหม? มันจะสร้างความแตกต่างหรือไม่ถ้าแอปพลิเคชันของฉันเป็น API ที่สร้างอยู่บนห้องสมุดภายนอกนี้มีไว้สำหรับใช้งานโดยโปรแกรมเมอร์อื่น ๆ ?


ดูเหมือนว่ารูปแบบของรูปแบบของอะแดปเตอร์แม้ว่ามันจะมีค่าที่น่าสงสัยที่นี่ (มันเป็นเพียงความสะดวกในการหลีกเลี่ยงการตั้งค่าพารามิเตอร์)
Robert Harvey

5
ทำไมไม่สร้างMakeCircle ฟังก์ชั่น ?
user253751

1
@immibis Thay เป็นความคิดแรกของฉัน เมื่อฉันสร้างเกมฉันมักจะสร้างฟังก์ชั่นตามแนวของmakePlayerตัวเองเท่านั้นที่ยอมรับ coords เพื่อวางผู้เล่นที่ แต่มอบหมายให้ผู้สร้างที่ซับซ้อนมากขึ้น
Carcigenicate

คำตอบ:


13

แม้ว่ามันจะไม่ได้แย่เสมอไป แต่เป็นเรื่องยากที่การแปลงโดยนัยเป็นตัวเลือกที่ดีที่สุดของคุณ

มีปัญหา

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

โดยทั่วไปมีวิธีแก้ปัญหาที่ดีกว่า

  1. สร้าง wrapper ของคุณเองที่ใช้คลาส / เฟรมเวิร์กอื่นภายใน
  2. สร้างเมธอดตัวช่วยที่ใช้อาร์กิวเมนต์ constuctor ที่คุณต้องการและป้อนค่าที่แก้ไขแล้วส่งคืนออบเจ็กต์จริงโดยไม่ต้องระบุอาร์กิวเมนต์ที่คุณไม่สนใจ
  3. สืบทอดจากคลาสปัญหาและจัดหาคอนสตรัคเตอร์ที่ดีกว่าของคุณเอง
  4. ตระหนักว่าการทะเลาะในการโต้แย้งพิเศษนั้นไม่ได้เป็นเรื่องใหญ่

โดยส่วนตัวแล้วฉันคิดว่า # 2 เป็นเครื่องมือที่ง่ายที่สุดในการติดตั้งและเป็นภาระน้อยที่สุดในการออกแบบ คนอื่นสามารถทำได้ดีตามสถานการณ์และสิ่งอื่นที่คุณพยายามทำกับชั้นเรียนเหล่านี้

การแปลงโดยนัยเป็นทางเลือกสุดท้ายและดูเหมือนจะคุ้มค่าจริงๆสำหรับฉันเมื่อฉันมีฟังก์ชั่น C ++ สไตล์ที่ฉันพยายามทำ - วัตถุกลยุทธ์ที่ฉันแปลงเป็นประเภทตัวแทนโดยปริยาย


1

เมื่อพิจารณาถึงสถานการณ์ที่คุณอธิบายคุณสามารถคิดถึงเรื่องนี้ในแง่ของการประยุกต์ใช้ฟังก์ชั่นบางส่วน

ตัวสร้างเป็นฟังก์ชั่น (อย่างน้อยก็ในทางทฤษฎีใน C # คุณสามารถสร้าง "ฟังก์ชั่นโรงงาน" ที่เรียกตัวสร้าง):

Func<double, Point, Flavour, Circle> MakeCircle = (r, p, f) => new Circle(r, p, f);

สำหรับการใช้งานบางส่วนต่อไปนี้จะพอเพียง:

public static Func<T1, T2, R> Partial<T1, T2, T3, R>(this Func<T1, T2, T3, R> func, T3 t3)
   => (t1, t2) => func(t1, t2, t3);

ตอนนี้คุณสามารถรับ Constructor ของคุณที่ต้องการเพียง 2 พารามิเตอร์เท่านั้น:

Func<double, Point, Circle> MakeCardboardCircle = Circle.Partial(Flavours.Cardboard)

ตอนนี้คุณมีฟังก์ชั่นจากโรงงานพร้อมพารามิเตอร์ที่คุณต้องการ

Circle c = MakeCardboardCircle(1.0, new Point(0, 0)))

BTW นี้เทียบเท่ากับตัวเลือก 2 ข้างต้นอย่างชัดเจนเพียงแค่จากมุมมองการทำงานที่มากขึ้น

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