Versioning with the new and override Keywords

   


Versioning with the new and override Keywords

A large proportion of the software written today is, as mentioned earlier developed by using class libraries often written by other remote programmers. Just like most standalone software applications are upgraded to versions with more features and less bugs, class libraries undergo a similar evolving process. It is a fairly painless process to upgrade to the latest version of the Doom game, but what if you want to upgrade the .NET Framework class library on which your application is heavily dependent. What if the library developers for example didn't like the name WriteLine anymore and changed it to PrintLine in the latest upgrade? You would then have to painstakingly substitute all the WriteLine calls in your code to PrintLine calls.

The problems and solutions related to class library upgrades are generally termed versioning. In this section we will deal with one particular versioning issue related to inheritance, which is elegantly handled by C#. This will make you appreciate why C# encourages us to use the new keyword (as shown in line 23 of Listing 17.9 if we are hiding a function member in a derived class and the keyword override if we are overriding it. It further shows you why non-virtual methods are the default and why the virtual keyword is explicitly required to declare a function to be virtual.

Often class library classes are reused by deriving your own classes from them. This was demonstrated earlier where we extended the System.Windows.FormsWinForms.Form class to display a simple GUI window.

Suppose you in a similar way, as illustrated in Listing 17.10 are writing a SpaceShuttle class by extending the Rocket class found in a class library written by a company called BlipSoft. Usually classes and class libraries exist inside dll assemblies as discussed in Chapter 15 and their code cannot be viewed, but for demonstration purposes I have inserted the Rocket class as part of the code shown in Listing 17.10.

Listing 17.10 Source code of SpaceShuttle.cs
01: using System; 02: 03: class Rocket 04: { 05:      // Rocket is part of a class library developed 06:      // and maintained by the BlipSoft software company 07:     private int age = 0; 08: 09:     public int Age 10:     { 11:         get 12:         { 13:             return age; 14:         } 15: 16:         set 17:         { 18:             age = value; 19:         } 20:     } 21: } 22: 23: class SpaceShuttle : Rocket 24: { 25:      //SpaceShuttle is written by you 26:     private int distanceTravelled = 0; 27: 28:     public int DistanceTravelled 29:     { 30:         get 31:         { 32:             return distanceTravelled; 33:         } 34:     } 35: 36:     public void MoveForward(int distanceAdded) 37:     { 38:         distanceTravelled += distanceAdded; 39:     } 40: } 41: 42: class Tester 43: { 44:     public static void Main() 45:     { 46:         SpaceShuttle columbia = new SpaceShuttle(); 47: 48:         columbia.MoveForward(30); 49:         Console.WriteLine("Distance travelled: { 0} ", 50:             columbia.DistanceTravelled); 51:     } 52: } Distance travelled: 30 

The Rocket class from BlipSoft does not include an instance variable to keep track of the distance traveled so you have included it in the SpaceShuttle class (line 26) along with the MoveForward method (lines 36-39) that adds a certain distance to the distanceTravelled instance variable. This all works fine until you receive a new upgrade of the class library from BlipSoft. By pure coincidence they have in this version added a virtual method to the Rocket base class with exactly the same name, return type and parameter types as your MoveForward method in the SpaceShuttle class. It looks like this:

 public virtual void MoveForward(int daysAdded) {     age += daysAdded; } 

You have no connection with BlipSoft other than the use of their class library so you have no idea that this method has been included. If the compiler, as is the case for several other programming languages, automatically assumed that a virtual method in a base class should be overridden by a method of the same signature in a descendant class then MoveForward of SpaceShuttle would override MoveForward of Rocket. This would be an error because the two methods perform completely unrelated actions: Rocket's MoveForward is adding days to the age instance variable whereas SpaceShuttle's MoveForward is adding a distance to the distanceTravelled instance variable. the compilers of these other languages give no hint to the programmer of the error, which could stay undetected for a period of time. This error however does not prevent the program from running and the error could stay undetected for a period of time.

NOTE

graphics/common.gif

If the code had been written in C++ then SpaceShuttle's MoveForward would automatically override Rocket's MoveForward without any warning. Any call to MoveForward through a variable of type Rocket containing an object of type SpaceShuttle would through dynamic binding call SpaceShuttle's MoveForward method.

If the code was written in Java and the two MoveForward methods contained different return types the program would fail to compile because an overriding method must return the same type as the type it is overriding.


The C# compiler prevents these problems by alerting you about the issue through the following warning when you compile your program with the upgraded class library:

 SpaceShuttle.cs(40,17): warning CS0114: 'SpaceShuttle.MoveForward(int)' hides inherited member 'Rocket.MoveForward(int)'. To make the current method override that implementation, add the override keyword. Otherwise add the new keyword. 

You now get the opportunity to show your intent either by declaring SpaceShuttle's MoveForward to be an overriding method or just to be a new method hiding Rocket's MoveForward method. In our case we must declare it new as shown here:

 36:     public new void MoveForward(int distanceAdded) 37:     { 38:         distanceTravelled += distanceAdded; 39:     } 

Notice that even if you don't follow the advice in the compiler's warning and refrain from including the new or the override keywords the program will still compile and SpaceShuttle's MoveForward method defaults to become a new hiding method. However the new and override keywords convey important information to people reading through your code so use them with care and make sure you eliminate all the compiler warnings.

Suppose the MoveForward method of the upgraded Rocket class was not suitable to be overridden and its designers accordingly declared it a non-virtual method by leaving out the virtual keyword and that this method would be shipped with the upgrade instead of the virtual MoveForward version shown before. Then there would be no doubt that SpaceShuttle's MoveForward was merely hiding Rocket's MoveForward because a non-virtual method can never be overridden. Furthermore there would be no issues regarding different return types and other details concerning overriding. In other words the two methods would be totally separate. Rocket's non-virtual MoveForward would not be able to "reach in" and create confusion in SpaceShuttle's MoveForward method like Rocket's virtual MoveForward sibling.

In general you can create more havoc in derived classes by adding virtual methods rather than non-virtual methods to your base classes especially when these are part of a class library used by separate programmers where the communication is limited. So even though the majority of your methods in general needs to be declared virtual, C# still requires you to explicitly declare a method to be virtual to avoid any non-intended virtual methods roaming in your code.

NOTE

graphics/common.gif

Virtual functions are slightly slower to execute than their non-virtual siblings, because the runtime dynamically need use a bit of processing power to determine which virtual method implementation to execute. In contrast the execution of a non-virtual method is determined and hardwire at compile time. This slight performance difference is another argument for making non-virtual functions the default.



   


C# Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 286
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net