Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Possible Duplicate:
Alternatives to type casting in your domain

I've run into this issue in a number of places and have solved it a bunch of different ways but looking for other solutions or opinions on how to address. The scenario is when you have a collection of objects all based off of the same superclass but you want to perform certain actions based only on instances of some of the subclasses.

One contrived example of this might be an HTML document made up of elements. You could have a superclass named HTMLELement and subclasses of Headings, Paragraphs, Images, Comments, etc. To invoke a common action across all of the objects you declare a virtual method in the superclass and specific implementations in all of the subclasses. So to render the document you could loop all of the different objects in the document and call a common Render() method on each instance.

It's the case where again using the same generic objects in the collection I want to perform different actions for instances of specific subclass (or set of subclasses). For example (an remember this is just an example) when iterating over the collection, elements with external links need to be downloaded (e.g. JS, CSS, images) and some might require additional parsing (JS, CSS). What's the best way to handle those special cases.

Some of the strategies I've used or seen used include:

  • Virtual methods in the base class.

So in the base class you have a virtual LoadExternalContent() method that does nothing and then override it in the specific subclasses that need to implement it. The benefit being that in the calling code there is no object testing you send the same message to each object and let most of them ignore it. Two downsides that I can think of. First it can make the base class very cluttered with methods that have nothing to do with most of the hierarchy. Second it assumes all of the work can be done in the called method and doesn't handle the case where there might be additional context specific actions in the calling code (i.e. you want to do something in the UI and not the model).

  • Have methods on the class to uniquely identify the objects.

This could include methods like ClassName() which return a string with the class name or other return values like enums or booleans (IsImage()). The benefit is that the calling code can use if or switch statements to filter objects to perform class specific actions. The downside is that for every new class you need to implement these methods and can look cluttered. Also performance could be less than some of the other options.

  • Use language features to identify objects.

This includes reflection and language operators to identify the objects. For example in C# there is the is operator that returns true if the instance matches the specified class. The benefit is no additional code to implement in your object hierarchy. The only downside seems to be the lack of using something like a switch statement and the fact that your calling code is a little more cluttered.

Are there other strategies I am missing? Thoughts on best approaches?

share|improve this question

marked as duplicate by pdr, Walter, ChrisF Nov 9 '12 at 16:24

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

add comment

2 Answers

Acording to Liskov substitition principle, LSP, a base class must be replaceable by any of its subclasses.

This principle makes possible that a calling code written for the superclass should work with a subclass designed later in time.

If the calling method needs to call methods that don't exist in the superclass, then such calling method wasn't designed around that superclass.

The best aproach is to improve the class design not to violate LISP.

In your example:

For example (an remember this is just an example) when iterating over the collection, elements with external links need to be downloaded (e.g. JS, CSS, images) and some might require additional parsing (JS, CSS).

The aditional parsing needs not be called from outside, breaking LISP. It's an under-the-hood behavior on the subclass that doesn't need to affect the superclass contract.

LoadExternalContent() should be a private methods of the subclass called in either the constructor or the Render method or other.

Also, you will find some behavior that should be promoted to the superclass. That's OK.

And finally: if you wrote a code that iterates a list of disparate objects and needs to call especific subclass methods, then that code is not written for the superclass/interface and casting the especific types is intrinsic to such a method.

share|improve this answer
add comment

One other possible approach is to use the visitor design pattern.
It gives you the possibility of implementing different behaviors in different classes each of which should implement one method that will operate on each type.
Its advantage over declaring virtual methods in the base class and override them is that you can extend your functionality by adding new classes rather than changing existing ones.

share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.