I have the following classes:
class Alpha
{
}
class Beta : Alpha
{
}
class Gamma : Beta
{
}
class Epsilon : Beta
{
}
And I have a couple methods where I take them as parameters:
void Receiver(Gamma gamma);
void Receiver(Epsilon epsilon);
void Receiver(Beta beta);
void Receiver(Alpha alpha);
I require something a bit unusual here.
I want to be able to pass Alpha objects to all methods, but I don’t want methods like void Receiver(Beta beta); being able to receive objects of types that inherit from Beta (that is, I want to, at worst, raise an Exception if a Gamma or Epsilon object is passed.
How can I best implement this in such a way that is generic enough?
I was thinking for the first part, I should have a method that allows for upcasting, such as
class Alpha
{
public T Upcast<T>() where T : Alpha
{
// somehow return a T
}
}
The issues here are that I want this to work on all levels, for instance I want being able to “upcast” Beta too.
The second part should be easier, as I would just throw on objects being passed that are above the type I require.
so something like this should suffice:
void Receiver(Epsilon epsilon)
{
// if epsilon inherits from Epsilon, throw.
}
Can you help me with the first part of my problem? Thanks!
You seem to be struggling with code that can deal with a given type, but it cannot be trusted to deal properly with subtypes. This is generally speaking a violation of many OOP principles, one of them being LSP, or Liskov Substitution Principle.
You might be in a place where you could consider the visitor pattern as a means of overcoming this problem. It’s very close to what you already have, with some minor modification, which is good! It’s nice when patterns emerge from your code, rather than being forced upon it.
Your
void Receivermethods are essentially already visitor implementations, so let’s rename them and create an interface.Your class that is handling the processing of each element type simply needs to implement that interface.
Then have each element type also implement a simple and common interface
(Strictly speaking, the interfaces aren’t necessary, it’s just good form.)
And there you go, a method of double dispatch where an element invokes a visitor method specific to its own type, even though you might have a reference to it via a base type.
If you have implemented it properly, you should see “Visiting Beta object” on the screen (or, in your terms, you should see the desired “Receiver” behavior executed.)
Another option you might consider is simply making
Receivera virtual method on your base class and let the derived classes override it, and have the behaviors inside the classes, if that makes sense for your hierarchy. If the behaviors need to be external, you could also consider a factory approach that knows how to create a specific processor for a given class. There are many options you have that do not involve your program going nuts if a subtype is passed to a method expecting the base.This is very strange indeed. And I’m not sure you actually want that. You seem to have the inheritance hierarchy flipped on its head, where super types can be substituted for derived types and not the other way around, and you should really rethink what you are trying to do.