Library tutorials & articles

A Twisted Look at Object Oriented Programming in C#

Shadow Fields, Override Virtual Methods

Well, I am going to finish this "nuts and bolts" chapter before I flame out! I promised that I would discuss overriding, so I am going to make good on this promise. In general when you extend a class, you shadow fields with the same name in the base class and override virtual methods with the same name and parameter list in the base class. Overriding makes the base class method invisible. Shadowing a field, only hides the field from view. You can still explicitly touch the hidden shadowed field if you wish. You cannot touch an invisible overridden method. To demonstrate the difference between shadowing and overriding I resort, as usual, to twisted code!

First, you can create a sample base class with a public read only field "toastTime" and a virtual method "MakeToast()":

class Base
{
    public readonly int toastTime= 60;
    public virtual void MakeToast()
    {
        System.Console.WriteLine("MakeToastInSeconds: " + toastTime.ToString());
    }
}

Declaring the only method virtual explicitly allows a designer to override the MakeToast() method in a subclass. (Contrast this to the approach in Java in which all methods are virtual by default.) This is important, since you are explicitly allowing a subclass to completely rewrite the implementation of the MakeToast() method and in doing so make it totally invisible!

Shadow Fields, Override Methods in the Base Class

Now you can extend or subclass the class Base:

/// <summary>
/// Summary description for SubClass
/// </summary>
class SubClass : Base
{
    public readonly new int toastTime= 1;
    public override void MakeToast()
    {
        System.Console.WriteLine("MakeToastInMinutes:" + toastTime.ToString());
    }
}

Note: You must explicitly tell the compiler that you are overriding the virtual base class method MakeToast() with the key word override and that you are hiding the base field with the key word new. (You cannot override a field in a base class.)

Overriding the method MakeToast makes the base class method with the same name and signature invisible to the caller of the class. This is in contrast to the base class field toastTime. The base class field toastTime is shadowed, but still potentially visible to the caller. You have shadowed a base class field and overridden a base class method.

You can demonstrate the behavior of shadowed fields with the following test code:

SubClass sc= new SubClass();
System.Console.WriteLine(sc.toastTime.ToString()); // --> 1
Base super= (Base)sc;
System.Console.WriteLine(super.toastTime.ToString()); // --> 60

In the above code snippet, the type of the reference variable determines which value of toastTime can be touched with the reference variable. Touching the field with a reference of type SubClass tells the compiler that you want to touch the the toastTime field of class SubClass. Casting the reference variable to the base type, tells the compiler that you want to touch the toastTime field of the type Base. Both fields are potentially visible to the caller. The base class field is shadowed, but still touchable.

You can demonstrate the behavior of an overridden method with the following test code. This code demonstrates that the overridden base class method MakeToast is invisible. You cannot touch the overridden method even if you cast the reference to the base type.

SubClass sc= new SubClass();
sc.MakeToast(); // --> MakeToastInMinutes: 1
Base super= (Base)sc;
super.MakeToast(); // --> MakeToastInMinutes: 1

Despite the cast, only the derived (specialized) class method is visible. If you think about it, this behavior is absolutely essential to polymorphism. Overriding insures that the "proper" implementation of a polymorphic method is called at runtime. You can demonstrate the proper polymorphic behavior with a little sample code. Here is yet another version of the Drawable class, now with a default implementation of DrawYourself.

class Drawable
{
    public virtual void DrawYourself()
    {
        System.Console.WriteLine("Drawable");
    }
}
class Square : Drawable
{
    public override void DrawYourself()
    {
        System.Console.WriteLine("Square");
    }
}
class Circle : Drawable
{
    public override void DrawYourself()
    {
        System.Console.WriteLine("Circle");
    }
}

Here is the sample code that demonstrates that the "proper" implementation is called at runtime.

Drawable draw= new Drawable();
draw.DrawYourself(); //--> Drawable
draw= new Square();
draw.DrawYourself(); //--> Square
draw= new Circle();
draw.DrawYourself(); //--> Circle

Overriding insures that the proper super class implementation is always called at runtime. The magic of polymorphism is secure.

You Can Hide a Method

For completeness sake, I will mention that you can hide a virtual method using the key word new instead of the key word override. Go ahead. Edit the previous code sample and replace the key word override with the key word new.

This is the new behavior that breaks polymorphism:

Drawable draw= new Drawable();
draw.DrawYourself(); //--> Drawable
draw= new Square();
draw.DrawYourself(); //--> Drawable
draw= new Circle();
draw.DrawYourself(); //--> Drawable

Perhaps not what you wanted!


Comments

  1. 18 Feb 2009 at 11:33
    That seems to be a good article...But I have a serious question... For example : to draw a sqare we need two points. and to draw a circle we need a point and a radius. How can we use interface and at the same time ;handle this situation . I think it cannot be done...Or if it can be done please let us know.
  2. 09 Jan 2007 at 10:08

    thanks for the useful info

    regards

     

  3. 18 Jul 2006 at 15:51

    If you have tried developing large extensible business applications where data needs are in the gigabytes if not terabytes in any static OO based programming language, then you are in for a lot of headaches. OOP does not lend itself well to this type of development as so called real world objects do not translate well into OO objects, most so called real world objects in the business world translate to data. This fact is lost on many managers, developers and analysts. Most applications in the real world are business related and not some academic project. I have been privy to many failed projects because of the selection of high level development language invariably they have always been statically typed. The one overlooked programming paradigm that has been neglected because of the OO hype is table or data driven programming. This form lends itself well to business related applications and can be used in conjunction with any programming paradigm but work wonders with a dynamically type languages. It is easily extensible, scalable and can be easily modified without throwing hundreds of users of the network.

    As for Interfaces, function overloading, generics, templates, reflection, RTTI, default parameters, adding scripting etc, these are kludges to make a static language do what a dynamic language already does, and done badly at that.

  4. 19 Jan 2006 at 17:09

    When I first learned OO programming I was primarily excited by code re-use on the object side of the equation. Objects considered as providers of services to other code that acts as a client.


    After many years of developing OO application I eventually grew to see the vast web of code dependencies and to realize that every piece of client code is itself serving some other code i.e. tier 1 calls tier 2 calls tier 3 (tier 2 code is being served by tier 3 but is serving tier 1). I realized that my objects provided a great deal of code re-use but what about all the code that used those objects? That is where Interfaces come in. Thanks to an interface all of your code that uses object A can be swapped out to use object B, C, D, or E regardless of the object type and therefore ancestry. Regardless of object implementation.


    In another sense, Interfaces are more "fair". If an object can perform the services declared in the interface then it can be used by code that uses the interface. This means no strict binding to particular object hierarchies and that can save a lot of headaches.

  5. 22 Mar 2004 at 10:56
    Moving from VB toC#? Looking for a lot of practical explanations of OO topics? Read this article.  Really good OO 'shot gun' intro to using C# with OO methodology.  This format should be used by publishers like O'Reilly to create a nice tidy OO break down, in a book.  This kind of material, to the point, all in one spot, explanation is sadly missing from most OO explanations.  The worst part about OO is buying into it.  If you come from a non OO or just didn't really use OO background, like I did, your probably looking for the 'why' as much as the 'how'.  This article, in what has to be said is few pages, really helped me see the worth and implementation of OO in C#.  I think that that is because the author uses the whole development approach to explain topics.  Meaning, not only is the raw abilities, the 'how' of OO shown (e.g like inheritance) but the author uses patterns to show the 'why'.  This article finally flicked the old proverbial light switch for me.  Obviously there is much more to OO than just how to program with a language that supports OO.  For me the missing link, was the connection with patterns.

    Read the article even if you work with OO, give it to people that are just starting OO.  

    I'd really like to see this article as the core of explaining more OO topics, in the same format.  
  6. 04 Mar 2004 at 12:54
    Tried doing print version, when i printed, out came tons of blank pages.

    Workaround:
    Save printable page as complete web page.

    Edit default.css file in _files subfolder of saved page.

    Change the CODE.Pre line to:

    CODE.pre {
       PADDING-RIGHT: 7pt; PADDING-LEFT: 7pt; WIDTH: 100%; COLOR: #000000; PADDING-TOP: 7pt; BACKGROUND-COLOR: #fbedbb
    }

    (removes the display:block)
  7. 20 Dec 2003 at 16:07

    RRIOS:
    Thanks for the excellent write up on this concept. It has actually helped quite a bit to give me a better perspective on the subject of Interfaces. I particularly liked your analogy of Royal family vs democracy.
    Thanks!

  8. 19 Dec 2003 at 14:37

    Inheritance is rigid. It´s like being born into the royal family. Sure, you get alot of privileges without doing anything, but you carry all the baggage and stigmas that come with your family name.  You can´t JOIN the royal family. You have to be born into it.


    Interfaces are democratic. A system that declares an interface is saying "I dont care who you are or how big or small you are: if you agree to these rules you may join the club". Think of your drivers license. The DVM declares an interface and ANYONE can use the road system as long as they stick to the rules (implement the interface).


    In programming terms, suppose you are using two systems, in one you have created a Vehicle class and have several child classes like Car, Bicycle, and Bus. In the other you have cooking items, say for a recipe system. You may have classes like Flour, Eggs, Carrot. These two groups of classes have nothing to do with each other.
    You create a third point of sale system for a retail store, and you plan to sell among other things, bicycles and flour. Your point of sale system could declare an IRetail interface that defines to other classes what they need to implement in order to participate in the Point of Sales system like Price(), TaxKey() and UPC().
    This means you can reuse your Bicycle and Flour classes, just by adding the implementation of the IRetail interface in order to use them in the Point of Sale system. This new system will be capable of handling any kind of object as long as it implements IRetail.


    So Interfaces are an advantage to both the system that declares the interface (they dont care what class of object they are handling)  and to the classes that implement them (they can participate in any system as long as they agree to the rules).

  9. 03 Dec 2003 at 06:22
  10. 11 Nov 2003 at 16:22

    An interface allows a developer, but more specifically a designer, to say "These features must be implemented." It is then up to the developer to work out the details of how to deliver on those features/abilities. It creates a boundary of expectation from other users of the object.


    They can say "Oh I i see it implements IInterface, therefore it will definitely have X, Y and Z". It is quite useful when you wnat to implement concepts in multiple objects instead of concrete functionality. For instance, say you had two types of collections one was a tree and one was a jagged array of parent/child IDs (which in many ways is a tree represented another way but they are syntactically different). If you wanted to implement something like "GetParent", you couldn't (well maybe you could, but go with me for the sake of example) implement one generic function for "GetParent" that would work for both the Jagged Array and the Tree. YOu could however have both objects implement an interface, and then have the developer do the syntactic details of returning an items parent.


    Anyway, more half baked analogies.

  11. 05 Nov 2003 at 16:26
    Very good analogy about interfaces. But ......why do we need them?
    One of the questions that still persists for me, (and something I have never seen a discussion on) is what real benefit Interfaces offer; it seems they offer some, but that it is somewhat limited. Let me give an analogy, in the form of an old joke. An engineer, a phycicist and an economist were on a desert island with a can of pineapple that had survived the boat wreck. Both the engineer and the physicist made multiple attempts using their scientific knowledge to open the can of pineapple, but to no avail. After some time the economist remarked: "This shouldn't be a difficult problem to solve." "Well, tell us", replied the engineer and physicist in unison. Said the economist, " Assume a can opener."
    This is what economists do. They make assumptions and think they have contributed something. Is this not like Interfaces, whose job, it appears, is to make policy statements without ever getting around to implementing anything? All the same amount of coding has to be done whether the interface is used or not; in fact there may be considerable duplication of code if minor changes to an implementation are needed. So what has been achieved? Not nearly as much, it seems, as inheritance would offer, were full inheritance of pure methods possible. This is perhaps why an Abstract class seems to be more useful.

    I would appreciate anyone who can resolve my perplexity here. I could learn something.
  12. 17 Oct 2003 at 21:41

    Pretty good article.  Its the first time i acutally laughed and smiled while reading your article.  Very good read..


    There are a few inaccuracies though just to point out...


    1.


    MyClass c;
    c.someMethod()


    does not throw a null reference exception. It actually throws a compiletime error "Use of unassigned local variable".  In c# variables much be assigned before use or something like that..


    2.
    array[] = new array[10]
    only returns an array of null references if it you are declaring an array of ref type.  If it is a value type, the values will be assigned their default values..


    and 3.
    comparing type compatibility in most cases should use "as" instead of "is" because if you use is before casting the type, you in effect check the type twice, once before the cast, and once during the cast..
    Its just an optimisation really..


    Other than that, like i said before, best read i have ever had.  Learned a few new words too like "gumption".  Who would have thought..

  13. 01 Oct 2003 at 16:59

    This intro to C-Sharp is a very good tutorial, but its only an intro. The naming of variables and methods need to be standardized for easier readability. It also does not cover data driven dynamic web apps.

  14. 29 Aug 2003 at 05:32

    Quote:
    What a shame the author never learnt to use a sensible standard for naming variables.


    ...it is a good article and Microsoft does advocate clearer naming of Object variables.


    It's a shame you never LEARNED proper grammer.

  15. 13 Aug 2003 at 23:36
    This is a seriously good intro article on OOP. What a shame the author never learnt to use a sensible standard for naming variables. Names like P, M, N, and at one stage an 'i' to represent (according to my school) 'dblInterest' just tend to obscure code and (I guess) put off less persistent student code nerds than myself.



  16. 01 Jan 1999 at 00:00

    This thread is for discussions of A Twisted Look at Object Oriented Programming in C#.

Leave a comment

Sign in or Join us (it's free).

Jeff Louie
AddThis

Related podcasts

  • Object-Oriented Programming in Ruby

    In this episode, I talk with Scott Bellware about object-oriented programming in Ruby, and Ruby's object model. This is taken from a private conversation, and the audio quality suffers at times. Much thanks to Scott for allowing this to be released.This episode of the Alt.NET Podcast is bro...

We'd love to hear what you think! Submit ideas or give us feedback