Overriding vs Hiding (Shadowing) ใน C#
ทั้งสองเกี่ยวกับการนิยามเมธอดใน Derived Class ที่มีชื่อเหมือน Base Class แต่วัตถุประสงค์และพฤติกรรมต่างกัน
Overriding (การเขียนทับ) - ใช้ virtual/override
- Base class ต้องระบุ
virtual(หรือabstract) - Derived class ใช้
override - **Polymorphism ทำงาน**: เรียกผ่าน Base reference ให้เมธอด Derived ทำงาน
- สามารถเข้าถึง Base implementation ได้ด้วย
base.Method()
class Animal
{
public virtual void Speak() => Console.WriteLine("Animal sound");
}
class Dog : Animal
{
public override void Speak() => Console.WriteLine("Woof!");
}
// ใช้งาน
Animal a = new Dog();
a.Speak(); // "Woof!" - Polymorphism ทำงาน
Hiding/Shadowing (การซ้อนเงา) - ใช้ new
- Base class **ไม่ต้อง** มี virtual
- Derived class ใช้
new(warning ถ้าไม่ใส่) - **ไม่มี Polymorphism**: เรียกผ่าน Base reference ให้ Base method ทำงาน
- Derived class มี implementation ของตัวเองแยกต่างหาก
class Animal
{
public void Speak() => Console.WriteLine("Animal sound");
}
class Dog : Animal
{
public new void Speak() => Console.WriteLine("Woof!");
}
// ใช้งาน
Animal a = new Dog();
a.Speak(); // "Animal sound" - Base method!
Dog d = new Dog();
d.Speak(); // "Woof!" - Derived method
ตารางเปรียบเทียบ
| คุณสมบัติ | Overriding | Hiding (Shadowing) |
|---|---|---|
| Base class keyword | virtual / abstract | ไม่จำเป็น (ปกติ) |
| Derived class keyword | override | new |
| Polymorphism | ✅ ทำงาน | ❌ ไม่ทำงาน |
| เข้าถึง Base method | base.Method() | ไม่ได้โดยตรง (ต้อง cast) |
| Compiler warning | ไม่มี (ถูกต้อง) | มี (ถ้าไม่ใส่ new) |
| วัตถุประสงค์ | ขยาย/เปลี่ยนพฤติกรรม | แทนที่/ซ่อน implementation |
ตัวอย่างครบ: เปรียบเทียบพร้อมกัน
using System;
class Base
{
public virtual void VirtualMethod() => Console.WriteLine("Base.Virtual");
public void NormalMethod() => Console.WriteLine("Base.Normal");
}
class Derived : Base
{
public override void VirtualMethod() => Console.WriteLine("Derived.Virtual (Override)");
public new void NormalMethod() => Console.WriteLine("Derived.Normal (Hiding)");
}
class Program
{
static void Main()
{
Base b = new Derived();
Derived d = new Derived();
Console.WriteLine("=== ผ่าน Base reference ===");
b.VirtualMethod(); // Derived.Virtual (Override) - Polymorphism
b.NormalMethod(); // Base.Normal - No polymorphism
Console.WriteLine("\n=== ผ่าน Derived reference ===");
d.VirtualMethod(); // Derived.Virtual
d.NormalMethod(); // Derived.Normal (Hiding)
}
}
ผลลัพธ์
=== ผ่าน Base reference ===
Derived.Virtual (Override)
Base.Normal
=== ผ่าน Derived reference ===
Derived.Virtual (Override)
Derived.Normal (Hiding)
เมื่อไหร่ควรใช้อะไร?
- Override: ต้องการ Polymorphism, ขยายพฤติกรรม Base, Liskov Substitution Principle
- Hiding (new): Base class ไม่ได้ design ให้ override, ต้องการ interface ใหม่ทั้งหมด, Versioning (base เพิ่มเมธอดใหม่ชนกับ derived)
Sealed Override - ป้องกัน Override เพิ่ม
class Base { public virtual void M() { } }
class Middle : Base { public sealed override void M() { } } // ไม่ให้ override ต่อ
class Derived : Middle { /* public override void M() { } */ } // ❌ Compile error