Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ความแตกต่างระหว่าง Overriding และ Shadowing ใน C#

Overriding (การเขียนทับ/ลบพรับ)

Derived Class นำเสนอ Implementation ใหม่สำหรับ Virtual/Abstract Method ของ Base Class ใช้คีย์เวิร์ด override เป็น Polymorphism จริง (Dynamic Dispatch)

Shadowing / Method Hiding (การซ่อน/เงา)

Derived Class สร้าง Member ใหม่ชื่อเดียวกับ Base Class ใช้คีย์เวิร์ด new ไม่ใช่ Polymorphism (Static Binding)

ตารางเปรียบเทียบรายละเอียด

คุณสมบัติ Overriding Shadowing (Hiding)
คีย์เวิร์ด virtual (Base) + override (Derived) new (Derived)
Base Method Requirement ต้องเป็น virtual, abstract, หรือ override ไม่ต้องการ (Member ใดก็ได้)
Polymorphism ✅ เป็น (Dynamic Dispatch) ❌ ไม่เป็น (Static Binding)
การเข้าถึง Base Member base.Method() Cast เป็น Base Type หรือ base.Method() (ใน Derived)
Signature ต้องเหมือนกันทุกประการ สามารถต่างกันได้ (Return Type, Parameters)
Access Modifier ต้องเหมือนกันหรือเข้าถึงได้มากกว่า อิสระ (เป็น Member ใหม่ทั้งหมด)
วัตถุประสงค์ ขยาย/เปลี่ยนพฤติกรรมแบบ Polymorphic แทนที่ Member เดิมอย่างสมบูรณ์

ตัวอย่าง Overriding

using System;

public class Shape {
    public virtual double Area() {
        return 0;
    }
}

public class Circle : Shape {
    public double Radius { get; set; }
    
    public override double Area() {
        return Math.PI * Radius * Radius;
    }
}

// Polymorphism ทำงาน
Shape s = new Circle { Radius = 5 };
Console.WriteLine(s.Area()); // 78.54 - เรียก Circle.Area()

ตัวอย่าง Shadowing

using System;

public class Parent {
    public void Display() {
        Console.WriteLine("Parent.Display()");
    }
    
    public int Value = 10;
}

public class Child : Parent {
    // Shadowing Method
    public new void Display() {
        Console.WriteLine("Child.Display()");
    }
    
    // Shadowing Field
    public new string Value = "Child";
}

// Static Binding - ขึ้นอยู่กับ Type ของ Variable
Parent p = new Child();
p.Display(); // "Parent.Display()"
Console.WriteLine(p.Value); // 10 (Parent.Value)

Child c = new Child();
c.Display(); // "Child.Display()"
Console.WriteLine(c.Value); // "Child" (Child.Value)

การเข้าถึง Base Member ใน Shadowing

public class Child : Parent {
    public new void Display() {
        // 1. ใช้ base keyword (ใน Derived Class)
        base.Display(); // เรียก Parent.Display()
        
        // 2. Cast เป็น Base Type
        ((Parent)this).Display();
        
        Console.WriteLine("Child.Display()");
    }
}

⚠️ ข้อควรระวัง Shadowing

  • ทำให้โค้ดสับสน - พฤติกรรมเปลี่ยนตาม Type ของตัวแปรอ้างอิง
  • Compiler จะเตือน Warning: 'Child.Display()' hides inherited member 'Parent.Display()'. Use the new keyword if hiding was intended.
  • ไม่ใช่ Polymorphism - ฉันแนะนำให้ใช้ Overriding แทนเมื่อเป็นไปได้
  • ใช้ Shadowing เฉพาะเมื่อ: ไม่สามารถแก้ Base Class ได้ (Third-party Library) หรือต้องการเปลี่ยน Signature เมธอด

สรุป: เลือกอะไรดี?

✅ ใช้ Overriding (virtual/override) ใน 95% ของกรณี - เป็น Polymorphism จริง โค้ดชัดเจน รองรับ Liskov Substitution Principle

⚠️ ใช้ Shadowing (new) เฉพาะกรณีบังคับ - เมื่อไม่ได้ควบคุม Base Class หรือต้องการเปลี่ยน Signature