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