Geeks With Blogs
Dave Chestnutt: SparklingCode and CodeGaffes Writing better code; for fun and profit
One of the benefits of object oriented design, is that some problems show up during compile-time instead of at run-time.  And you know that run-time issues always show up at the worst possible time, like at a customer site.
 
This CodeGaffe happens when a programmer writes code that "enforces" something with comments, or Assertions.  Have you ever seen a method defined in a base class with a comment or Assertion telling you to override it?  Of course, if the subclass doesn't override it, you can be certain the method will be called at an inopportune time. This is a simple misunderstanding of an object oriented feature because there is a way to make the language work for you to force the subclass author to override the method.
 
So what's this CodeGaffe look like?

 
    public class TableBase
    {
        public virtual int CountLines()
        {
            Debug.Assert(false, "override me");  // *** Don't do this
            return 0;
        }
    }
 
    public class MyTableSubclass : TableBase  // subclass
    {
    }
 
    public static void Main(string[] args)        // here is code to use it
    {
        MyTableSubclass table = new MyTableSubclass ();
        Console.WriteLine(table.CountLines());  // prints 0 after assert
    }


 
See the problem?  As the original author of TableBase, you want to make sure people who write subclasses implement their own CountLines method.  But if they forget to override it, they won't know until the method is called at runtime.   Possibly at a customer site, but more likely during testing.  
 
Instead, define your base class this way:

 
    public abstract class TableBase           // *** Do use "abstract"
    {
        public abstract int CountLines();     // *** Do use "abstract"
    }
 
    public class MyTableSubclass : TableBase  // now this won't compile
    {
    }

 

Now, if someone extends your class, they'll find out at compile-time -- that's about as immediate as you can get without standing behind them, watching over their shoulder as they code.  And fixing the subclass at this time is trivial because the error points to the actual problem: a missing definition for CountLines.

 


 

    public abstract class TableBase
    {
        public abstract int CountLines(); // *** "abstract" forces your intent
    }
   

    public class MyTableSubclass : TableBase
    {
        public override int CountLines() // the new method definition
        {
            return 1;
        }
    }

 

    public static void Main(string[] args) // here is code to use it
    {
        MyTableSubclass table = new MyTableSubclass ();
        Console.WriteLine(table.CountLines());  // outputs "1", as it should 
    }
       


 

The moral?  If you find yourself creating (or maintaining) a method with comments or assertions telling people to override it -- make the method abstract.  And you'll enforce your intention.

 

Technorati tags: ,

Posted on Monday, January 16, 2006 4:51 PM CodeGaffes | Back to top


Comments on this post: CodeGaffe: Unreinforced Concrete Classes

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Dave Chestnutt | Powered by: GeeksWithBlogs.net