Overriding (การเขียนทับแบบ Polymorphic)
Derived Class ให้ Implementation ใหม่สำหรับ Virtual/Abstract Method ของ Base Class รองรับ Polymorphism แบบ Dynamic Dispatch
ตัวอย่าง Overriding ด้วย Abstract Class
using System;
namespace PolymorphismApplication {
// Abstract Base Class
public abstract class Shape {
// Abstract Method - บังคับ Override, ไม่มี Body
public abstract int Area();
}
// Derived Class
public class Rectangle : Shape {
private int _length;
private int _width;
public Rectangle(int a = 0, int b = 0) {
_length = a;
_width = b;
}
// Override Abstract Method
public override int Area() {
Console.WriteLine("Rectangle class area:");
return _width * _length;
}
}
class RectangleTester {
static void Main(string[] args) {
Rectangle r = new Rectangle(10, 7);
double a = r.Area();
Console.WriteLine("Area: {0}", a);
Console.ReadKey();
}
}
}
ผลลัพธ์
Rectangle class area:
Area: 70
Shadowing / Method Hiding (การซ่อน)
Derived Class สร้าง Member ใหม่ชื่อเดียวกันด้วยคีย์เวิร์ด new ไม่ใช่ Polymorphism
ตัวอย่าง Shadowing
using System;
using System.Collections.Generic;
class Demo {
public class Parent {
public string Display() {
return "Parent Class!";
}
}
public class Child : Parent {
// Shadowing ด้วย new keyword
public new string Display() {
return "Child Class!";
}
}
static void Main(String[] args) {
Child child = new Child();
Console.WriteLine(child.Display()); // "Child Class!"
// แต่อ้างอิงผ่าน Parent Type
Parent parent = child;
Console.WriteLine(parent.Display()); // "Parent Class!" - เรียก Base Method!
}
}
ผลลัพธ์
Child Class!
Parent Class!
ความแตกต่างสำคัญ: การทำงานกับ Base Reference
// Overriding - Polymorphic
Shape shape = new Circle(5);
shape.Draw(); // เรียก Circle.Draw() ✅
// Shadowing - Non-Polymorphic
Parent p = new Child();
p.Display(); // เรียก Parent.Display() ❌ (ไม่ใช่ Child.Display())
ตารางสรุปความแตกต่าง
| ด้านเปรียบเทียบ | Overriding | Shadowing |
|---|---|---|
| คีย์เวิร์ด | virtual/abstract + override | new |
| Polymorphism | ✅ รองรับ | ❌ ไม่รองรับ |
| Base Method ต้อง Virtual? | ✅ บังคับ | ❌ ไม่จำเป็น |
| Signature ต้องเหมือน? | ✅ บังคับ | ❌ ไม่บังคับ |
| การเข้าถึง Base | base.Method() | Cast หรือ base.Method() (ใน Derived) |
| Runtime Behavior | ขึ้นอยู่กับ Object จริง | ขึ้นอยู่กับ Reference Type |
แนวทางปฏิบัติที่ดี (Best Practices)
- Default Choice: ใช้ Overriding - เป็น OOP ที่ถูกต้อง รองรับ Polymorphism
- Avoid Shadowing: Shadowing ทำให้โค้ดสับสน ขัดต่อ Liskov Substitution Principle
- ใช้ Shadowing เฉพาะ: Third-party Library ที่ไม่ได้ Mark Virtual, หรือต้องการเปลี่ยน Return Type/Parameters
- ใส่ new Keyword: ถ้า Shadowing จริงใจ ให้ใส่
newเพื่อป้องกัน Warning และบอกเจตนา