Các bài tập Microsoft .NET 86 Virtual Methods Tuy nhiên, hãy xem trường hợp ta code như sau: Private Sub BtnParentClassObject_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnParentClassObject.Click Dim obj As ClassCha obj = New ClassCon() obj.ChàoHỏi() End Sub Trước hết, ở đây có vẻ kỳ kỳ, tại sao declare một variable loại ClassCha mà lại instantiate một object ClassCon. Chuyện đó hoàn toàn bình thường, vì ClassCon là một ClassCha. Tức là một variable loại ClassCha hay ClassCon đều có thể chứa, thật ra là hold references to (point to, chỉ tới), một instance của ClassCon. Điểm này áp dụng tổng quát khi ta dùng Inheritance. Một variable loại SuperClass có thể hold reference to bất cứ SubClass Object nào thừa kế từ SuperClass ấy. Đó là một cách để ta implement tính đa dạng (polymorphism). Đều có thể làm ta ngạc nhiên là khi ta click button BtnParentClassObject ta cũng thấy hiển thị message " Thưa các Bác". Các bài tập Microsoft .NET 87 Sao lạ vậy? Variable obj được declared là ClassCha tại sao message không phải là "Chào các cháu"? Lý do là Sub ChàoHỏi của ClassCon được gọi thay vì Sub ChàoHỏi của ClassCha. Ta nói Sub ChàoHỏi là Virtual method. Tất cả methods trong VB.NET đều là virtual. Ý niệm virtual để nói rằng cái implementation của con cháu trẻ nhất trong dòng họ được dùng - không cần biết là variable có data type là class của thế hệ nào trong dòng họ. Tức là, nếu variable dùng trong client code hold references to ClassÔngNội, ClassCha, ClassCon hay ClassCháu thì method trong ClassCháu được gọi. Nếu trong ClassCháu không có implementation của method thì ta gọi method trong ClassCon, nếu không có thì gọi method trong ClassCha .v.v theo thứ tự từ bề dưới lên bề trên. Keyword Me Keyword Me được dùng khi ta muốn nói rõ (explicitly) rằng ta muốn dùng method của chính cái Class đang chứa code ấy, chớ không phải một implementation nào khác của method ấy. Cũng có trường hợp ta phải dùng keyword Me để nói ta muốn dùng class- level variable chớ không phải procedure-level variable có cùng tên. Một procedure-level variable, tức là local variable của một method, có cùng tên với một class-level variable được gọi là shadowed variable. Thí dụ: Public Class TheClass Private strName As String Public Sub DoSomething() Dim strName As String Các bài tập Microsoft .NET 88 strName = "Quang" End Sub End Class Ở đây, variable strName được declared ở class-level và bên trong Sub DoSomething. Bên trong method ấy local variables (kể cả shadowed variables) sẽ được dùng vì chúng che đậy class-level variables trừ khi ta nói rõ rằng phải dùng variable của class-level bằng cách dùng keyword Me: Public Class TheClass Private strName As String Public Sub DoSomething() Dim strName As String strName = "Quang" ' thay đổi value của local (shadowed) variable Me.strName = "Kim" ' thay đổi value của class-level variable End Sub End Class Keyword MyBase Keyword Me rất tiện dụng khi ta muốn dùng Class members của chính Class chứa code. Tương tự như vậy, đôi khi ta muốn dùng Class method của BaseClass (cũng gọi là SuperClass), chớ không phải một implementation của method ấy trong SubClass. Nhớ là một virtual method luôn luôn gọi implementation của Class trẻ nhất. Từ trong một SubClass, nếu muốn gọi một method của BaseClass ta dùng keyword MyBase như sau: Public Class ClassCon Inherits ClassCha Public Overrides Sub ChàoHỏi() MessageBox.Show("Thưa các Bác", "Class Con") MyBase.ChàoHỏi() End Sub Các bài tập Microsoft .NET 89 End Class Bây giờ nếu ta chạy Sub ChàoHỏi của ClassCon ta sẽ có hai messages, một cái từ ClassCon theo sau bởi một cái từ ClassCha. MyBase chỉ nói đến BaseClass trực tiếp, tức là Class cha thôi chớ không nói đến Class ông nội. Không có cách nào để nói đến hơn một thế hệ. Dầu vậy, keyword Mybase có thể được dùng cho bất cứ thứ gì đã được declared Public, Friend hay Protected trong ParentClass. Điều này kể luôn cả những thứ mà ParentClass thừa kế từ các thế hệ trước trong gia đình, tức là ClassÔngNội, ClassÔngCố .v.v Keyword MyClass Vì lý do virtual method, ta sẽ gặp những trường hợp rắc rối như khi code của ParentClass lại chạy code của SubClasses. Khi viết code của một class, từ method này ta thường gọi những methods khác nằm trong cùng class. Thí dụ như: Public Class ClassCha Public Sub VôĐề() ChàoHỏi() End Sub Public Overridable Sub ChàoHỏi() MessageBox.Show("Chào các cháu", "Class Cha") End Sub End Class Trong trường hợp này, VôĐề gọi Sub ChàoHỏi để đón tiếp. Để ý là vì ChàoHỏi được declared Overridable nên rất có thể một SubClass sẽ implement method ChàoHỏi và lấn quyền nó. Thí dụ: Public Class ClassCon Inherits ClassCha Public Overrides Sub ChàoHỏi() MessageBox.Show("Thưa các Bác", "Class Con") Các bài tập Microsoft .NET 90 End Sub End Class Vì đặc tính virtual của ChàoHỏi nên ta tưởng ClassCha execute chính Sub ChàoHỏi của nó nhưng té ra nó lại execute code của ChàoHỏi trong ClassCon. Trong code dưới đây, một Object ClassCon gọi Sub VôĐề của ClassCha: Private Sub BtnSubClassObject_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnSubClassObject.Click Dim obj As New ClassCon() obj.VôĐề() End Sub Trong ClassCha, Sub VôĐề gọi ChàoHỏi của chính nó, tuy nhiên Sub ChàoHỏi ấy bị overridden bởi implementation của ChàoHỏi trong ClassCon. Do đó, program sẽ hiển thị message "Thưa các Bác". Nếu ta không muốn như vậy, ta muốn VôĐề execute chính code của ChàoHỏi trong ClassCha thì phải dùng keyword MyClass như sau: Public Class ClassCha Public Sub VôĐề() MyClass.ChàoHỏi() End Sub Public Overridable Sub ChàoHỏi() MessageBox.Show("Chào các cháu", "Class Cha") End Sub End Class Ở đây ta không thể dùng keyword Me vì VôĐề có gọi ChàoHỏi ở class- level trong ClassCha chớ không phải trong một SubClass, nhưng bị overridden. Hình dưới đây minh họa quá trình gọi VôĐề từ client code: . implement tính đa dạng (polymorphism). Đều có thể làm ta ngạc nhiên là khi ta click button BtnParentClassObject ta cũng thấy hiển thị message " Thưa các Bác". Các bài tập Microsoft .NET. Các bài tập Microsoft .NET 86 Virtual Methods Tuy nhiên, hãy xem trường hợp ta code như sau: Private Sub. Class TheClass Private strName As String Public Sub DoSomething() Dim strName As String Các bài tập Microsoft .NET 88 strName = "Quang" End Sub End Class Ở đây, variable strName