Amazon.com Widgets Authoring Generics: A Simple First Step

Authoring Generics: A Simple First Step

By Nick at March 19, 2012 15:39
Filed Under: Delphi, Software Development

Consumer or Producer?

By now I suspect that most of you have heard of generics.  Perhaps you have started using them via the Generics.Collections unit, where you can find TList<T>TStack<T>, etc.  The Delphi Spring Framework contains an even more sophisticated set of collections and interfaces to those collections, including the very powerful IEnumerable<T>

These are all very useful classes, and our code is made much simpler, easier to maintain, and more type-safe because of them.  But using them merely makes us consumers of generics.  If we want to truly take advantage of generics, we need to become producers of generic classes.  It’s a big step to see the benefit of generic collections, but the truly big step is to start seeing opportunities for the use of generics in your own code.

A Contrived, Simple Example

This past weekend, some of my team members and I attended the C-Sharpen event here in Philly.  It was a valuable day, made particularly so by the presentations given by Steve Bohlen.  He gave an excellent presentation on the topic I discussed above – how we need to start thinking as producers of generics and not merely consumers.  In that presentation, he gave a simple example of how generics are powerful and can make your code simpler, more effective, and more powerful.  So, I’m going to show that example here.  It’s a bit contrived, but very illustrative of how to think about generics.

First, consider the following code:

type

  TOrderItem = class
    ID: integer;
  end;

  TOrder = class
    ID: integer;
  end;

  TCustomer = class
    ID: TGUID;
  end;

Now this code is very simple – a set of classes that might represent a simple order entry system.  But right away, something should occur to you.  All three have something in common – they are entities in your system. Down the road, you may want to act upon all the entities in your system, so you might create a superclass like so:

type

  TEntity = class  
  end;

  TOrderItem = class(TEntity)
    ID: integer;
  end;

  TOrder = class(TEntity)
    ID: integer;
  end;

  TCustomer = class(TEntity)
    ID: TGUID;
  end;

But you might be frustrated because you want your TEntity class to have an ID field that is in use by all descendants, but that pesky TCustomer class can’t oblige – it needs a GUID for its ID tag instead of an integer like the other classes.

Instead of fretting about the different types of ID tags, how about just create one that doesn’t care what type it is?  Well, this is where the power of generics comes in.   How about you give the TEntity class a parameterized type – a generic – as  it’s ID, and then just tell all the classes what type their ID tag will be?

type

  TEntity<T> = class
    ID: T; 
  end;

  TOrderItem = class(TEntity<integer>)
  end;

  TOrder = class(TEntity<integer>)
  end; 

  TCustomer = class(TEntity<TGUID>)
  end;

Now, given the above, your entities can all have ID’s, but you don’t have to have the same type for all of them.  If a TEntity descendant needs an ID of a different type, you can just descend from TEntity and pass the correct ID type in the class declaration.  

Again, the example is quite contrived, but I think it does a nice job of showing how you can starting “thinking generically” and not just accept a rigid type structure. 

In addition, it illustrates why the more formal name for generics is “parameterized types”.  The type in the brackets is passed in to the type declaration, and then used within the class, just as method parameters are passed in to functions and procedures. 

A simple, contrived example, sure.  But hopefully it illustrates how generics can be used to turn you from a consumer of generic classes to making them a common tool in your code.

 

Update:

As a number of commenters have pointed out, my original example was sub-optimal.  Rather than post a "correction" post, I've taken the liberty of updating and improving the original article.

blog comments powered by Disqus

My Book

A Pithy Quote for You

"Nothing is wrong with California that a rise in the ocean level wouldn't cure."    –  Ross MacDonald

Amazon Gift Cards

General Disclaimer

The views I express here are entirely my own and not necessarily those of any other rational person or organization.  However, I strongly recommend that you agree with pretty much everything I say because, well, I'm right.  Most of the time. Except when I'm not, in which case, you shouldn't agree with me.