June 26, 2005 Uncategorized

External Polymorpism

So I have been posting an awful lot about oop exception handling. The approach that I have been following makes use of external polymorphism. As far as I can tell Chris Cleeland and Douglas C. Schmidt were the first to document its use as a pattern. They implemented with templates in C++. An OOP language with reflective abilities can achieve a similar effect. Before we dive into the implementation lets get some context, get on the same page as to what we are trying to solve.

Allow classes unrelated by inheritance or related by inheritance but without the desired virtual method to be treated polymorphically.

If you read the paper Douglas and Chris wrote my last sentence should sound familiar. Now a little motivation would be nice too.

Say I found that the best solution for my problem was to implement the Visitor pattern but the class that I would need to alter are not in my control. They are classes that have been purchased in a third party library.

I want to focus on explaining the implementation not on justifying the need for this pattern. Justification is worth at least a whole other blog entry. So on to the participants.

For the moment let’s go with encapsulating all method implementations in one class. We want to be able to have a method implementation selected because it is associated with a type. In internal polymorphism this association is drawn through the type that implements the method. Here it will be drawn by the type of the parameter in the signature of the method (i.e. internal = type.method(), external = method(type)).

public class ExternalVisitor

{

    public void Accept(Animal animal) {}

    public void Visit(Parrot animal){}

    public void Visit(Alligator animal){}

}

Posted by Hello

I mentioned reflection earlier, that plus the concept of double dispatch can achieve external polymorphism. The Accept method on the class ExternalVisitor will use these concepts to dispatch to the method associated to the type of Animal pass it. It will reflect on the type passed as well as the methods named Visit searching for the method that accepts a parameter of the same or inherited type as passed. So if passed a Parrot the Visit method that accepts a parameter of type Parrot will be selected. The call will then be dispatched to that method (double dispatch). The call was redirected to the appropriate method, or double dispatched. If there is a type Cockatoo that inherits from Parrot it too would be dispatched to the method named Visit accepting a parameter of type Parrot.

I have packaged all the reflection stuff into a class called DoubleDispatchReflector. It is included in the ASOGS projects Patterns namespace. Here is some example usage.

public class ExternalVisitor

{

    public void Accept(Animal animal)

    {

        DoubleDispatchReflector dispatch = new DoubleDispatchReflector(this, “Visit”);

        dispatch.Invoke(animal);

    }

    public void Visit(Parrot animal){}

    public void Visit(Alligator animal){}

}

I don’t know about you but I think that provided a lot of bang for your buck. Two lines and we have the guts of external polymorphism working.

The participants explained so far implement all the methods to be dispatched to in one class. Lets change perspective and imagine that we have found someone else’s ExternalVisitor and we would like to reuse some of it’s methods and create some of our own. We would like to aggregate some of our own new code and reuse some old code.

Posted by Hello

This scenario has been packaged up into a class named Prizm. It too is included in the ASOGS projects Patterns namespace. And again here is some example usage.

public class AggregateVisitor

{

    public void Accept(Animal animal)

    {

        Prizm aggregate = new Prizm();

        object[] ParameterLists = new object[1];

        ParameterLists[1] = new Type[1] {typeof(Cockatoo)};

        aggregate.AddHandler(new NewExternalVisitor(), “Visit”, ParameterLists);

        ParameterLists[1] = new Type[1] {typeof(Parrot)};

        aggregate.AddHandler(new OldExternalVisitor(), “Visit”, ParameterLists);

        aggregate.Invoke(animal);

    }

}

Well that seems to be more than enough for this post. Maybe next time I will write about using multiple parameters.

Note:

I have not yet released the aggregation class (Prizm) and there have been modification to the DoubleDispatchReflector since it’s last release.

The examples shown here are not for production use. They have been made for easy reading.

10,377 Total Views

Leave a comment

*

here