เมื่อใดจึงจะย้ายเขตข้อมูลทั่วไปลงในคลาสพื้นฐานได้


16

ขณะนี้ฉันมีคลาสที่ได้รับสองคลาสAและBที่ทั้งสองมีเขตข้อมูลร่วมกันและฉันพยายามที่จะตรวจสอบว่ามันควรจะขึ้นไปในชั้นฐาน

มันไม่เคยอ้างถึงจากชั้นฐานและบอกว่าในบางจุดลงมาที่ถนนอีกชั้นจะได้รับCที่ไม่ได้_field1แล้วจะไม่เป็นหลักของ "สิทธิพิเศษน้อย" (หรือบางสิ่งบางอย่าง) ถ้ามันถูกละเมิด เป็น?

public abstract class Base
{
    // Should _field1 be brought up to Base?
    //protected int Field1 { get; set; }
}

public class A : Base
{
    private int _field1;
}

public class B : Base
{
    private int _field1;
}

public class C : Base
{
    // Doesn't have/reference _field1
}

18
ผมคิดว่าคำถามนี้ก็ไม่มีความชัดเจนเพราะคุณไม่ได้ให้เราความคิดของสิ่งใดBase, A, B, Cและ_field1มี นี่เป็นรายละเอียดที่สำคัญที่ไม่ควรถูกทิ้งไว้ ฉันคิดว่าคุณควรแก้ไขคำถามเพื่อพูดคุยเกี่ยวกับสิ่งเหล่านั้น
แทนเนอร์ Swett

ตามคำตอบที่ฉันต้องการ: สร้างพาหนะใหม่เพื่อให้มีระบบกันสะเทือนเสมือนจากนั้นรถยนต์และจักรยานอาจมีล้อและเรืออาจมีการลอยตัวซึ่งจะทำให้สิ่งที่เป็นนามธรรมขึ้นไป ฉันพบว่าถ้าสิ่งที่เป็นนามธรรมของฉันนำไปสู่การตั้งค่าเฉพาะโดยตรงฉันก็ไม่ได้ย้ายแนวความคิดที่ไกลเกินพอ
Patrick Hughes

6
อย่าใช้การสืบทอดคลาสเพื่อหลีกเลี่ยงการทำซ้ำรหัส ใช้สำหรับการสืบทอดและขยายพฤติกรรมเช่น polymorphism ย้ายเขตข้อมูลทั่วไปไปยังคลาสพื้นฐานถ้าหากมีเหตุผลในฟิลด์เดียวกันไม่ใช่สองส่วนของข้อมูลที่ไม่เกี่ยวข้องซึ่งเกิดขึ้นเพื่อใช้ชื่อเดียวกันในบริบทที่เกี่ยวข้อง
แบรนดอน

ทำไมคุณถึงมีคลาสพื้นฐานเพื่อเริ่มต้นด้วย
jpmc26

คำตอบ:


34

ทุกอย่างขึ้นอยู่กับปัญหาที่แน่นอนที่คุณพยายามแก้ไข

พิจารณาตัวอย่างที่เป็นรูปธรรม: ระดับฐานของคุณเป็นนามธรรมVehicleและคุณยังมีการใช้งานที่เป็นรูปธรรมและBicycle Carคุณกำลังพิจารณาย้ายnumberOfWheelsจากBicycleและCarยานพาหนะ คุณควรทำเช่นนี้? No! เพราะรถทุกคันไม่มีล้อ คุณสามารถบอกได้ว่าถ้าคุณพยายามที่จะเพิ่มBoatชั้นเรียนแล้วมันจะแตก

ทีนี้ถ้าคลาสฐานที่เป็นนามธรรมของคุณWheeledVehicleมันเป็นตรรกะที่จะมีnumberOfWheelsตัวแปรสมาชิกอยู่ในนั้น

คุณจำเป็นต้องใช้ตรรกะเดียวกันกับปัญหาของคุณเพราะอย่างที่คุณเห็นมันไม่ใช่คำตอบที่ง่ายหรือใช่


3
หนึ่งสามารถยอมรับได้ชั่วคราวว่า 0 คือ numberOfWheels ที่ถูกต้อง อย่างไรก็ตามในที่สุดคุณอาจเพิ่มroll()วิธีการซึ่งเป็นจุดที่ความคิดของคลาสย่อยกำลังมองล่วงหน้า
949300

11
เรือมี 0 ล้อ อะไรที่ทำลาย
D Drmmr

14
@Drmmr ไม่ใช่ว่า Boat มีล้อ 0 ล้อนั่นล้อไม่ได้เป็นแนวคิดสำหรับเรือดังนั้นโมเดลของคุณไม่ควรอนุญาต
Peter M

10
ประเด็นของฉันคือตัวอย่างไม่ดี ไม่มีอะไรผิดปกติทางแนวคิดเกี่ยวกับยานพาหนะ (ที่เกิดขึ้นกับเรือ) โดยระบุว่ามีล้อ 0 ล้อ
D Drmmr

10
จากนั้นทุกอย่างจะตกนรกเมื่อคุณต้องการเก็บเรือพาย
IllusiveBrian

13

การพูดอย่างมีเหตุผลนอกเหนือจากการวางเขตข้อมูลที่จำลองแบบในคลาสย่อย vs. โดยทั่วไปในคลาสฐานมีตัวเลือกที่สามคือซึ่งจะแนะนำคลาสย่อยใหม่ในลำดับชั้นที่มีคุณสมบัติทั่วไประหว่างทั้งสอง @ คำใบ้เกี่ยวกับเรื่องนี้โดยไม่ได้ไปที่นั่นอย่างเต็มที่

โดยใช้ตัวอย่างของ @ Pete เราจะแนะนำคลาสย่อย (อาจเป็นนามธรรม) สำหรับ Wheeled Vehicle ที่สืบทอดมาจากคลาสฐานดั้งเดิม - ในขณะที่คลาสย่อยทั้งสองลงมาจากคลาสนั้น ดังนั้นคลาสพื้นฐานดั้งเดิมไม่ได้ปนเปื้อนกับล้อ แต่ความธรรมดาของล้อคือ DRY (ไม่ซ้ำในหมู่คลาสย่อยที่มีล้อ)

ซึ่งแน่นอนว่าอาจเกินความเป็นจริงตามวัตถุประสงค์ของคุณ แต่ได้รับการสนับสนุนโดยกลไกลำดับชั้นของชั้นเรียน


นี่คือสิ่งที่ฉันตัดสินใจทำ (A และ B ทับกันส่วนใหญ่ดังนั้น B จะได้มาจาก A)
Samis

9

ฉันจะเล่นเป็นทนายของปีศาจที่นี่

ตอนนี้คุณไม่ควรทำอะไรเลย

มันแห้งไหม ไม่ได้ แต่จะดีกว่าถ้ามีการทำซ้ำเล็กน้อยกว่าสิ่งที่เป็นนามธรรมก่อนเวลาอันควรซึ่งคุณไม่สามารถถอยออกได้ในภายหลัง refactor เพื่อย้ายคุณสมบัติไปยังคลาสพื้นฐานทั่วไปนั้นง่าย ไปในทางอื่นไม่ได้ รอดู.

เมื่อทำการตัดสินใจแบบนี้ฉันมักจะใช้ "กฎ 3": เมื่อฉันทำสิ่งเดียวกันซ้ำแล้วซ้ำอีกในสามแห่งที่แตกต่างกันและจากนั้นฉันจะพิจารณาย้ายห่วงโซ่ขึ้นมา NB คุณเท่านั้นที่ 2


2
การสังเกตอย่างชาญฉลาดนั่นคือฉันจะบอกว่าจำเป็นสำหรับการตัดสินใจ
Radarbob

1
ฉันเห็นด้วยส่วนใหญ่ แต่ "ตอนนี้" (ไม่มีรหัสพิเศษอย่างที่เราเห็น) การเปลี่ยนโครงสร้างในทั้งสองทิศทางนั้นไม่สำคัญ แต่ถ้ามีรหัสเพิ่มเติมซึ่งใช้ฟิลด์การเปลี่ยนโครงสร้างในทั้งสองทิศทางอาจยากขึ้นอย่างมาก
Doc Brown

2

โดยทั่วไปฉันจะย้ายไปที่ชั้นฐาน ฉันไม่คิดว่ามีวัตถุประสงค์ใช่ / ไม่ใช่เพราะมีการแลกเปลี่ยนที่นี่ - การดำเนินการในสาขาที่ไม่ได้ใช้กับการลดความซับซ้อน

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

คลาส 'ตัวกลาง' ที่แนะนำฟิลด์ทั่วไปจะใช้ได้ถ้าคุณมีฟิลด์จำนวน จำกัด มาก แต่โปรดทราบว่าวิธีการนี้สามารถเพิ่มความซับซ้อนได้อย่างมากหากคุณมีหลายสิบฟิลด์ที่ใช้ในชุดค่าผสมที่แตกต่างกันซึ่งนำไปสู่คลาสตัวกลางจำนวนมากแต่ละชุดจะแนะนำชุดเขตข้อมูลเฉพาะ ที่อาจกลายเป็นปัญหาการบำรุงรักษา


ตัวอย่างของฉันไม่สำคัญแม้ว่ามันจะยังเป็นรหัสการผลิต คุณสร้างอาร์กิวเมนต์ที่ดีในการ "ลดระดับ" ลำดับชั้นด้วยคลาสฐาน "หนัก" ซึ่งฉันก็จะเห็นว่าตัวเองเอนไปในกรณีเช่นนี้
Samis

1
@samis: คุณใช้คลาสที่ชื่อ "A, B, C" และ "Base" โดยมีเพียงฟิลด์เดียวและไม่มีวิธีใดในรหัสการผลิต ฉันถามว่า
Doc Brown
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.