PDA

View Full Version : [Q] new, virtual và override trong C#



White_Rose
12-02-2003, 15:38
Giả sử mình có class Window và class Button như trong hai trừong hợp sau:


public class Window
{
public void DrawWindow()
{
//........
}
}

public class Button:Window
{
public new void DrawWindow()
{
base.DrawWindow();
//.......
}
}




public class Window
{
public virtual void DrawWindow()
{
//.....
}
}

public class Button:Window
{
public override void DrawWindow()
{
base.DrawWindow();
//.....
}
}

Vậy sự khác nhau giữa hai cách implemention này là gì?

Ở cách thứ hai, nếu sử dụng:


public class Button:Window
{
public new virtual void DrawWindow()
{
//.......
}
}

thì khi code như sau:


Button button = new Button();
Window wbutton = new Button();
button.DrawWindow();
wbutton.DrawWindow();

thì DrawWindow() nào được gọi? có gì khác so với sử dụng override không? Nếu có thì khác nhau như thế nào vậy?
Cảm ơn mọi ý kiến

consoilangthang
12-02-2003, 18:04
1. khi không cho rằng overriding method DrawWindow là cần thiết (method DrawWindow của bạn là okie rồi), thì khai báo như đoạn code 1 của bạn :


class Window {
public void DrawWindow() { // stuff };
}

mọi object Obj kiểu Window, khi invoke Obj.DrawWindow() sẽ luôn được CLR thực thi Window.DrawWindow().

@ ở class Button, thực ra không cần keyword new (sẽ nhận được một warning từ compiler - hình như thế :D). Keyword new là một cách để bạn khẳng định với compiler rằng method Button.DrawWindow không có liên hệ đa hình đa hiếc gì đến method cùng tên của class Window, và bạn kiểm soát được sự trùng tên của 2 methodz (compiler sợ bạn bị nhầm lẫn nên xuất warning để cho bạn cơ hội xác nhận mưu đồ của bản thân).

2. keyword virtual là đèn xanh cho overriding method (từ đó -> polymorphism), thế nên, đoạn code 2 mang ý nghĩa đa hình. Để hiểu rõ, ta xem ví dụ của bạn :


Button button = new Button();
Window wbutton = new Button();
/*
wbutton IS-A reference which can reference to
any Window object (certainly including any Button object,
'coz Button is derived from Window). Currently, it's
referencing to a Button object, rite ?
*/
button.DrawWindow(); // Button.DrawWindow() is called.
wbutton.DrawWindow(); // Button.DrawWindow() is called.


vì wbutton là một tham chiếu kiểu Window, nên khi thấy wbutton.DrawWindow(), CLR sẽ dò đến method Window.DrawWindow trước. Tuy nhiên :

.thứ nhất : do method Window.DrawWindow có flag virtual được bật lên (nôm na là cho phép ngó tiếp xuống sub-class dưới nếu có thể)...
.thứ hai : bản thân wbutton đang trỏ tới một object kiểu Button thứ thiệt (Button vốn là sub-class của Window), và method Button.DrawWindow có flag override được bật...

nên CLR sẽ thực thi method Button.DrawWindow.

@ trong trường hợp method Button.DrawWindow không có keyword new hay override, hình như sẽ nhận được warning. Nếu bất chấp warning, effect sẽ tương được với trường hợp từ khoá new được đặt vào.

p/s : không được rõ ràng cho lắm và cũng chưa chắc... chính xác, nhưng thông cảm nha, xót tiền net quá nên làm lẹ lẹ :D. Tốt nhất là nên check lại. Hehehe...

ddvtien
11-06-2010, 17:17
Sao tui không hiểu gì hết vậy !!!!

duongvannam
28-03-2011, 11:00
tui cũng chả hỉu gì hết :D

DotNetViet
07-07-2011, 16:18
Các từ khóa virtual được sử dụng để sửa đổi một method or property được khai báo, trong trường hợp này, method or property được gọi là virtual member. Cách thực thi của virutal member có thể bị thay đổi bằng cách override tại lớp kế thừa

Khi một virtual method được gọi, hệ thống sẽ kiểm tra xem nó có được override hay không. Nếu có thì nó sẽ thực thi override tại lớp chứa override, nếu không thì nó sẽ thực thi virtual member đã được định nghĩa ngay tại lớp đó.

Mặc định, các method không được khai báo virtual thì không thể override

Không thể sử dụng virtual với các từ khóa sau trong quá trình khai báo: static, abstract, override

Virtual property chạy giống abstract method, ngoại trừ sự khác biệt trong cách khai báo

// cs_virtual_keyword.cs
// Virtual and override
using System;
class TestClass
{
public class Dimensions
{
public const double pi = Math.PI;
protected double x, y;
public Dimensions()
{
}
public Dimensions (double x, double y)
{
this.x = x;
this.y = y;
}

public virtual double Area()
{
return x*y;
}
}

public class Circle: Dimensions
{
public Circle(double r): base(r, 0)
{
}

public override double Area()
{
return pi * x * x;
}
}

class Sphere: Dimensions
{
public Sphere(double r): base(r, 0)
{
}

public override double Area()
{
return 4 * pi * x * x;
}
}

class Cylinder: Dimensions
{
public Cylinder(double r, double h): base(r, h)
{
}

public override double Area()
{
return 2*pi*x*x + 2*pi*x*y;
}
}

public static void Main()
{
double r = 3.0, h = 5.0;
Dimensions c = new Circle(r);
Dimensions s = new Sphere(r);
Dimensions l = new Cylinder(r, h);
// Display results:
Console.WriteLine("Area of Circle = {0:F2}", c.Area());
Console.WriteLine("Area of Sphere = {0:F2}", s.Area());
Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
}
}

kết quả:
Area of Circle = 28.27
Area of Sphere = 113.10
Area of Cylinder = 150.80

trong code của bạn
ở đoạn 1 là cách override áp dụng cho những method không có từ khóa virtual
đoạn 2: sử dụng virtual
đoạn 3: override ở lớp cha và cho phép lớp kế thừa nó override

cách viết
Button button = new Button();
Window wbutton = new Button();
button.DrawWindow();
wbutton.DrawWindow();
đều gọi method DrawWindow() đã được implement ở class Button