logo

Dot Net-Bài 6-Những chức năng Đối Tượng mới của VB.NET (phần III)

Tham khảo tài liệu 'dot net-bài 6-những chức năng đối tượng mới của vb.net (phần iii)', công nghệ thông tin, kỹ thuật lập trình phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả
Bài 6 Những chức năng Đối Tượng mới của VB.NET (phần  III) Dùng OO trong VB.NET Ngăn cản Thừa kế Bình thường (By default) class nào cũng có thể được dùng làm base class để từ đó ta  thừa kế. Nhưng đôi khi ta không muốn cho ai thừa kế từ một Class nào đó, để làm việc  ấy ta dùng keyword NotInheritable khi declare class: Public NotInheritable Class KhôngCon End Class Khi ta đã dùng keyword NotInheritable rồi thì không class nào có thể dùng keyword  Inherits để tạo một subclass từ class ấy.  Thừa kế và Phạm vi hoạt động Khi ta dùng đặc tính thừa kế để tạo một SubClass thì class mới nầy có đủ mọi  methods, propertỉes và variables với Access Modifier Public hay Friend của  SuperClass. Bất cứ thứ gì declared là Private trong SuperClass thì SubClass không  thấy hay dùng được. Có một ngoại lệ là New method. Các Constructor methods cần phải được   implemented (định nghĩa) lại trong mỗi SubClass. Một chốc nữa ta sẽ bàn vào chi tiết về điểm nầy. Để làm sáng tỏ vấn đề SubClass có thể dùng Class Members nào của SuperClass, ta  thử code lại Function Amount trong LineItem class bằng cách khiến nó gọi một  Private Function tên CalculateAmount để tính ra Amount thay vì để nó tính trực tiếp  như trước đây: Public Function Amount() As Single Return CalculateAmount End Function Private Function CalculateAmount() As Single Return mintQuantity * msngPrice End Function Khi ta SubClass LineItem để tạo ra ServiceLine class, bất cứ Object ServiceLine nào  cũng thừa kế Function Amount vì Function ấy được declared Public trong BaseClass  LineItem. Ngược lại, vì Function CalculateAmount là Private nên cả ServiceLine class  lẫn bất cứ client code nào dùng một LineItem Object đều không truy cập nó được. Như thế, mặc dầu ta gọi Function Amount được, nhưng đến phiên nó gọi Private  Function CalculateAmount thì có bị trở ngại không? Không sao cả. Vì Function  Amount nằm trong cùng Class với Private Function CalculateAmount nên nó có thể  gọi được, dù rằng ta gọi Function Amount từ ServiceLine hay client code. Thí dụ trong client code ta có những hàng code như sau: Protected Sub BtnShowAmount_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnShowAmount.Click Dim Service As ServiceLine Service = New ServiceLine() Service.Item = "Delivery" Service.Price = 50 Service.DateProvided = Now MessageBox.Show (Service.Amount.ToString, "Amount", MessageBoxButtons.OK, MessageBoxIcon.Information) End Sub Kết quả sẽ được hiển thị trong message box, cho thấy Function CalculateAmount  được Function Amount gọi dùm cho client code dù rằng cả client code lẫn ServiceLine  code đều không thể gọi trực tiếp được. Điểm nầy nhắc tôi nhớ lại khi còn bé, có lần bà con trong vườn đem ra chợ cho ba má  tôi cả thúng xoài thơm rất ngon. Bạn tôi ở lối xóm thấy vậy biểu tôi lén lấy hai trái xoài  để ăn vụn. Vì không phải là người nhà nên bạn tôi không thể lấy đuợc xoài, bởi Access  Modifier của thún xoài là Private trong nhà tôi. Nhưng vì tôi là Public, nên bạn tôi có  thể nhờ tôi lấy dùm.  Protected Methods Đôi khi Public hay Private thôi chưa đủ. Nếu ta declare thứ gì Private thì nó hoàn  toàn giới hạn trong class, ngược lại nếu ta declare nó Public (hay Friend) thì nó có thể  được dùng trong subclasses hay client code.  Tuy nhiên, có lúc ta muốn một class member chỉ có thể được dùng trong subclasses  thôi, chớ không cho client code dùng. Trong trường hợp ấy ta dùng keyword  Protected. Thí dụ: Public Class FatherClass Protected DiSản As Single End Class Public Class SonClass Inherits FatherClass Public Function ChiaCủa() As Single Return Disản End Function End Class Ở đây ta có BaseClass FatherClass với Protected Field Disản. Không có client  code nào có thể thấy Field DiSản được. Thế nhưng bất cứ SubClass nào của  FatherClass cũng đều thừa kế và dùng được DiSản. Trong thí dụ trên, một lần nữa SubClass có một Public method (ChiaCủa) có thể  return một protected value ­ nhưng chính value ấy, DiSản, không trực tiếp cho phép  client code dùng.  Overriding Methods Chúng ta biết rằng đặc tính quan trọng của Inheritance là một SubClass chẳng những  thừa kế behaviours của ParentClass mà còn có thể override (lấn quyền) các  behaviours ấy nữa. Chúng ta đã thấy một SubClass có thể extend (thêm ra)  ParentClass bằng cách cho thêm các methods Public, Protected và Friend. Hơn nữa,  khi dùng overriding, một SubClass có thể alter (sửa đổi) behaviours của các methods  trong ParentClass. Bình thường (By default), ta không thể override methods trong ParentClass trừ khi các  methods ấy được declared với keyword Overridable trong ParentClass. Thí dụ: Public Class ClassCha Public Overridable Sub ChàoHỏi() MessageBox.Show("Chào các cháu", "Class Cha") End Sub End Class Tiếp theo, khi tạo một SubClass, nếu muốn ta có thể override behaviour của Sub  ChàoHỏi bằng cách dùng keyword Overrides như sau: Public Class ClassCon Inherits ClassCha Public Overrides Sub ChàoHỏi() MessageBox.Show("Thưa các Bác", "Class Con") End Sub End Class Bây giờ ta có thể viết client code như sau: Private Sub BtnSubClassObject_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles BtnSubClassObject.Click Dim obj As New ClassCon() obj.ChàoHỏi() End Sub Khi ta click button BtnSubClassObject program sẽ hiển thị message dialog dưới đây:  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".  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.  Bạn có thể Download source code của program nầy tại đây.  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 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 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") 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: Sub VôĐề thật ra nằm trong ClassCha mà ClassCon thừa kế nên VôĐề được  executed trong ClassCha và gọi Sub ChàoHỏi trong cùng class ( ClassCha). Nhưng vì  ClassCon có một implementation của Sub ChàoHỏi nên nó overrides ChàoHỏi của  ClassCha.  Overridding Method New Chúng ta đã thấy ta có thể override methods và dùng các keywords Me, MyBase và  MyClass để gọi các overriden methods trong dây chuyền thừa kế. Tuy nhiên, đối với  Constructor của class thì có những luật lệ đặc biệt dành riêng cho method New. Những methods New không tự động di truyền từ BaseClass xuống SubClass. Mỗi  SubClass phải có một implementation riêng cho Constructor dù rằng, nếu muốn, nó có  thể gọi vào BaseClass với keyword MyBase: Public Class ClassCon Inherits ClassCha Public Sub New() MyBase.New() ' để thêm các code khác để initialise tại đây End Sub End Class Khi gọi Constructor của BaseClass, ta phải gọi nó trước nhất ­ nếu không sẽ bị error.  Tuy nhiên ta không cần gọi Constructor của BaseClass vì Constructor của BaseClass  được gọi tự động. Có một luật đặc biệt là nếu tất cả methods New trong BaseClass đều đòi hỏi  parameters thì ta phải implement ít nhất một method New trong SubClass và ta phải  đặt statement MyBase.New ngay phía đầu. Dĩ nhiên là ta có thể Overload method New trong SubClass, nhưng ta phải tự lo liệu  cách gọi một method New thích hợp trong BaseClass.  Tạo BaseClasses và Abstract Methods Cho đến giờ ta đã bàn về virtual method với đặc tính override trong nguyên tắc thừa  kế. Trong các thí dụ trước đây BaseClass được instantiated thành Object để làm  chuyện nầy, chuyện kia. Nhưng đôi khi ta muốn tạo một BaseClass chỉ để dùng cho  thừa kế mà thôi.  Keyword MustInherit (Phải được Thừa Kế)  Trở lại cái thí dụ về Inheritance với Class LineItem. Sở dĩ ta đặt ra Class LineItem là vì  nó chứa những thứ chung cho cả hai classes ProductLine và ServiceLine. Chớ thật ra  một Object của Class LineItem không chứa đủ mọi đặc tính để làm một việc gì thực tế.  Nếu ta muốn nói rõ rằng Class LineItem chỉ được dùng để tạo những SubClasses  bằng cách thừa kế từ nó, ta có thể declare như sau: Public MustInherit Class LineItem Tức là ta chỉ thêm keyword MustInherit thôi, chớ không thay đổi gì khác. Kết quả là từ  nay Client code không thể instantiate một Object từ Class LineItem. Do đó dòng code  sau sẽ bị syntax error: Dim myObject As New LineItem() Thay vào đó, nếu muốn dùng LineItem ta phải tạo SubClass từ nó.  Keyword MustOverride (Phải bị Lấn Quyền) Tương tự với ý niệm Phải­được­thừa­kế trong Class, ta cũng có MustOverride cho  một method. Có thể trong BaseClass ta khai báo một method, nhưng ta đòi hỏi  method ấy phải có một implementation trong SubClass. Ta declare như sau: Dim MustOverride Sub CalculatePrice Để ý là ở đây không có thân thể của Sub CalculatePrice hay statement End Sub gì cả.  Khi dùng MustOverride ta không được phép cung cấp một implementation cho method  trong BaseClass. Một method như thế được gọi là abstract method hay pure virtual  function, vì nó chỉ có phần khai báo chớ không có phần định nghĩa. Những abstract  methods phải được overridden trong bất cứ SubClass nào của BaseClass thì mới dùng  được. Nếu không, ta sẽ không có phần implementation của method đâu cả và khi  compile sẽ gặp syntax error.  Abstract Base Classes Nếu hợp cả hai ý niệm MustInherit và MustOverride lại ta sẽ tạo ra một abstract base  class. Đây là một Class chỉ có khai báo chớ hoàn toàn không có implementation. Ta  phải SubClass từ nó thì mới làm việc được, thí dụ như: Public MustInherit Class ClassCha Public MustOverride Sub VôĐề() Public MustOverride Sub ChàoHỏi() End Class Kỹ thuật nầy rất thích hợp để ta code cái sườn hay bố cục của program ngay trong lúc  thiết kế. Class nào thừa kế ClassCha thì phải implement cả Sub VôĐề lẫn Sub  ChàoHỏi, nếu không sẽ bị syntax error. Nhìn về một phương diện, abstract base class rất giống khai báo Interface. Nếu dùng  Interface, chúng ta có thể khai báo như sau: Public Interface ICha Sub VôĐề() Sub ChàoHỏi() End Interface Bất cứ class nào chịu implement interface ICha thì phải implement cả Sub VôĐề lẫn  Sub ChàoHỏi, nếu không sẽ bị syntax error ­ do đó, ta thấy Interface rất giống một  abstract base class. Sự khác biệt chính giữa abstract base class với Interface là ở chỗ thừa kế. Khi ta tạo  một class con bằng cách SubClass từ ClassCha, chính class con ấy lại cũng có thể  được SubClassed. Mấy class cháu nầy sẽ tự động thừa kế VôĐề và ChàoHỏi từ class  con. Trong khi ấy nói về Interface, mỗi class phải tự implement ICha một cách độc lập và  phải cung cấp hai Subs VôĐề và ChàoHỏi của chính nó. Vì thế, nếu ta không có ý  định dùng lại code của các Subs khi ta tạo các classes mới thì ta có thể dùng  interface. Ngược lại nếu ta muốn dùng lại code trong SubClass theo nguyên tắc thừa  kế thì ta nên dùng abstract base class. 
DMCA.com Protection Status Copyright by webtailieu.net