Specific type or interface?
I have the following use case, a lot of code that was tightly coupled on a specific type (say Concrete1). Later it turned out that the specific type needs to be changed, so the interface is defined. for example
Class ABC {
virtual int foo() = 0;
virtual int getType() = 0;
}
class Concrete1 : public ABC {
int foo() {
... }
int getType() {
return 1;
}
}
class Concrete2 : public ABC {
int foo() {
... }
int getType() {
return 2;
}
}
A static factory pattern was used to create the objects. So, all the places where the new Concrete1 object was created are replaced with ABCFactory :: createType ().
Now in the code there are many places where I need to check whether the object returned by createType is concrete1 or Concrete2 and, accordingly, the corresponding logic (so many, if still in the code :().
I want to avoid a lot if still in code as part of this change. Any suggestions?
What worries me is
if (abc.getType() == 1) {
...
} else if (abc.getType() ==2) {
...
}
source to share
the whole point of using interfaces is that you can use polymorphism, which means you never have to check what type of instance is. this is a very big code smell (see Fowlers Refacotring). move the conditional logic to concrete classes and add a te function that will handle it in the interface
EDIT (adding example code from the moment the message was created from the mobile):
You are trying to do:
void Main(string[] args)
{
Bird bird = BirdFactory.GetPigeon();
if (bird.GetType().Equals(typeof(Duck)))
{
Console.WriteLine("quack");
}
else if (bird.GetType().Equals(typeof(Pigeon)))
{
Console.WriteLine("coo coo");
}
}
Try this instead:
interface Bird
{
void Speak();
}
class Duck : Bird
{
void Speak()
{
Console.Write("quack");
}
}
class Pigeon : Bird
{
void Speak()
{
Console.Write("coo coo");
}
}
void Main(string[] args)
{
Bird bird = BirdFactory.GetPigeon();
bird.Speak();
}
source to share
Place ...
another virtual method inside the implementation:
if (abc.getType() == 1) {
... // A
} else if (abc.getType() == 2) {
... // B
}
Place A and B like this:
class ABC {
virtual int foo() = 0;
virtual void doIt() = 0; // choose a proper name
};
class Concrete1 : public ABC {
int foo() {
... }
void doIt() {
... // A
}
};
class Concrete2 : public ABC {
int foo() {
... }
void doIt() {
... // B
}
};
And change yours if on
abc.doIt();
Like another one said that exactly the point of dynamic dispatch! Besides being more concise, it never forgets to handle the type. By executing your switch, you can silently handle a specific type, because you missed updating your code at that point when you introduced a new implementation. Also be aware of the virtual destructor in ABC.
source to share
If you are checking and / or including a type at runtime, you may need to use runtime type information if available to your compiler. It adds some overhead, but it does what you are trying to do without creating or maintaining a methodology of its own.
Unlike the purists, I'm not really "putting functionality in a class so you can use polymorphism to get around the switch type." Both are valid approaches (although the "in-class" method is not always possible and / or conceptually clean).
source to share