Sunday, May 17, 2020
Overrides in VB.NET - Using VB.NET Series
This is one of a mini-series that covers the differences in Overloads, Shadows, and Overrides in VB.NET. This article covers Overrides. The articles that cover the others are here: - Overloads- Shadows These techniques can be hugely confusing; there are a lot of combinations of these keywords and the underlying inheritance options. Microsofts own documentation doesnt begin to do the topic justice and there is a lot of bad, or out of date information on the web. The best advice to be sure that your program is coded correctly is, Test, test, and test again. In this series, well look at them one at a time with emphasis on the differences. Overrides The thing that Shadows, Overloads, and Overrides all have in common is that they reuse the name of elements while changing what happens. Shadows and Overloads can operate both within the same class or when a class inherits another class. Overrides, however, can only be used in a derived class (sometimes called a child class) that inherits from a base class (sometimes called a parent class). And Overrides is the hammer; it lets you entirely replace a method (or a property) from a base class. In the article about classes and the Shadows keyword (See: Shadows in VB.NET), a function was added to show that an inherited procedure could be referenced. Public Class ProfessionalContact ... code not shown ... Public Function HashTheName( ByVal nm As String) As String Return nm.GetHashCode End Function End Class The code that instantiates a class derived from this one (CodedProfessionalContact in the example) can call this method because its inherited. In the example, I used the VB.NET GetHashCode method to keep the code simple and this returned a fairly useless result, the value -520086483. Suppose I wanted a different result returned instead but, - I cant change the base class. (Maybe all I have is compiled code from a vendor.) ... and ... - I cant change the calling code (Maybe there are a thousand copies and I cant update them.) If I can update the derived class, then I can change the result returned. (For example, the code could be part of an updatable DLL.) There is one problem. Because its so comprehensive and powerful, you have to have permission from the base class to use Overrides. But well-designed code libraries provide it. (Your code libraries are all well designed, right?) For example, the Microsoft provided function we just used is overridable. Heres an example of the syntax. Public Overridable Function GetHashCode As Integer So that keyword has to be present in our example base class as well. Public Overridable Function HashTheName( ByVal nm As String) As String Overriding the method is now as simple as providing a new one with the Overrides keyword. Visual Studio again gives you a running start by filling in the code for you with AutoComplete. When you enter ... Public Overrides Function HashTheName( Visual Studio adds the rest of the code automatically as soon as you type the opening parenthesis, including the return statement which only calls the original function from the base class. (If youre just adding something, this is usually a good thing to do after your new code executes anyway.) Public Overrides Function HashTheName( nm As String) As String Return MyBase.HashTheName(nm) End Function In this case, however, Im going to replace the method with something else equally useless just to illustrate how its done: The VB.NET function that will reverse the string. Public Overrides Function HashTheName( nm As String) As String Return Microsoft.VisualBasic.StrReverse(nm) End Function Now the calling code gets an entirely different result. (Compare with the result in the article about Shadows.) ContactID: 246 BusinessName: Villain Defeaters, GmbH Hash of the BusinessName: HbmG ,sretaefeD nialliV You can override properties too. Suppose you decided that ContactID values greater than 123 would not be allowed and should default to 111. You can just override the property and change it when the property is saved: Private _ContactID As Integer Public Overrides Property ContactID As Integer Get Return _ContactID End Get Set(ByVal value As Integer) If value 123 Then _ContactID 111 Else _ContactID value End If End Set End Property Then you get this result when a larger value is passed: ContactID: 111 BusinessName: Damsel Rescuers, LTD By the way, in the example code so far, integer values are doubled in the New subroutine (See the article on Shadows), so an integer of 123 is changed to 246 and then changed again to 111. VB.NET gives you, even more, control by allowing a base class to specifically require or deny a derived class to override using the MustOverride and NotOverridable keywords in the base class. But both of these are used in fairly specific cases. First, NotOverridable. Since the default for a public class is NotOverridable, why should you ever need to specify it? If you try it on the HashTheName function in the base class, you get a syntax error, but the text of the error message gives you a clue: NotOverridable cannot be specified for methods that do not override another method. The default for an overridden method is just the opposite: Overrideable. So if you want overriding to definitely stop there, you have to specify NotOverridable on that method. In our example code: Public NotOverridable Overrides Function HashTheName( ... Then if the class CodedProfessionalContact is, in turn, inherited ... Public Class NotOverridableEx Inherits CodedProfessionalContact ... the function HashTheName cannot be overriden in that class. An element that cannot be overridden is sometimes called a sealed element. A fundamental part of the .NET Foundation is to require that the purpose of every class is explicitly defined to remove all uncertainty. A problem in previous OOP languages has been called ââ¬Å"the fragile base class.â⬠This happens when a base class adds a new method with the same name as a method name in a subclass that inherits from a base class. The programmer writing the subclass didnt plan on overriding the base class, but this is exactly what happens anyway. This has been known to result in the cry of the wounded programmer, I didnt change anything, but my program crashed anyway. If there is a possibility that a class will be updated in the future and create this problem, declare it as NotOverridable. MustOverride is most often used in what is called an Abstract Class. (In C#, the same thing uses the keyword Abstract!) This is a class that just provides a template and youre expected to fill it with your own code. Microsoft provides this example of one: Public MustInherit Class WashingMachine Sub New() Code to instantiate the class goes here. End sub Public MustOverride Sub Wash Public MustOverride Sub Rinse (loadSize as Integer) Public MustOverride Function Spin (speed as Integer) as Long End Class To continue Microsofts example, washing machines will do these things (Wash, Rinse and Spin) quite differently, so theres no advantage of defining the function in the base class. But there is an advantage in making sure that any class that inherits this one does define them. The solution: an abstract class. If you need even more explanation about the differences between Overloads and Overrides, a completely different example is developed in a Quick Tip: Overloads Versus Overrides VB.NET gives you even more control by allowing a base class to specifically require or deny a derived class to override using the MustOverride and NotOverridable keywords in the base class. But both of these are used in fairly specific cases. First, NotOverridable. Since the default for a public class is NotOverridable, why should you ever need to specify it? If you try it on the HashTheName function in the base class, you get a syntax error, but the text of the error message gives you a clue: NotOverridable cannot be specified for methods that do not override another method. The default for an overridden method is just the opposite: Overrideable. So if you want overriding to definitely stop there, you have to specify NotOverridable on that method. In our example code: Public NotOverridable Overrides Function HashTheName( ... Then if the class CodedProfessionalContact is, in turn, inherited ... Public Class NotOverridableEx Inherits CodedProfessionalContact ... the function HashTheName cannot be overriden in that class. An element that cannot be overridden is sometimes called a sealed element. A fundamental part of the .NET Foundation is to require that the purpose of every class is explicitly defined to remove all uncertainty. A problem in previous OOP languages has been called ââ¬Å"the fragile base class.â⬠This happens when a base class adds a new method with the same name as a method name in a subclass that inherits from a base class. The programmer writing the subclass didnt plan on overriding the base class, but this is exactly what happens anyway. This has been known to result in the cry of the wounded programmer, I didnt change anything, but my program crashed anyway. If there is a possibility that a class will be updated in the future and create this problem, declare it as NotOverridable. MustOverride is most often used in what is called an Abstract Class. (In C#, the same thing uses the keyword Abstract!) This is a class that just provides a template and youre expected to fill it with your own code. Microsoft provides this example of one: Public MustInherit Class WashingMachine Sub New() Code to instantiate the class goes here. End sub Public MustOverride Sub Wash Public MustOverride Sub Rinse (loadSize as Integer) Public MustOverride Function Spin (speed as Integer) as Long End Class To continue Microsofts example, washing machines will do these things (Wash, Rinse and Spin) quite differently, so theres no advantage of defining the function in the base class. But there is an advantage in making sure that any class that inherits this one does define them. The solution: an abstract class. If you need even more explanation about the differences between Overloads and Overrides, a completely different example is developed in a Quick Tip: Overloads Versus Overrides
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.