Reputation: 265
This question is related to the concept of object oriented design.
In the following example code (C#), I have an abstract base class Feature
, which has two subclasses: SubFeature1
and SubFeature2
. In my main program, I want to instantiate each of them by giving the correspondent parameter (name of class as a string) to the unique method instantiateFeature()
.
When I run this code, I get an error that basically states that the type OOP_example.Feature
cannot implicitely converted to OOP_example.SubFeature1
because an explicite conversion is already existing.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OOP_example
{
class Program
{
static void Main(string[] args)
{
Organization myOrga = new Organization();
SubFeature1 subObj1 = myOrga.instantiateFeature("SubFeature1");
SubFeature2 subObj2 = myOrga.instantiateFeature("SubFeature2");
}
}
public class Organization
{
Feature obj;
public Feature instantiateFeature(string s)
{
if (s.Equals("SubFeature1"))
{
obj = new SubFeature1();
}
else if (s.Equals("SubFeature2"))
{
obj = new SubFeature2();
}
return obj;
}
}
public abstract class Feature
{
public abstract void doSomething();
}
public class SubFeature1 : Feature
{
private int[] _val1;
//constructor
public SubFeature1()
{
_val1 = new int[2];
_val1[0] = 1;
_val1[1] = 2;
}
//this is the only method that inherits from class Feature
public override void doSomething()
{
//not implemented yet
}
//this is some other class that does not inherit from Feature
public void doSomethingElse()
{
//not implemented yet
}
}
public class SubFeature2 : Feature
{
private int[] _val1;
//constructor
public SubFeature2()
{
_val1 = new int[2];
_val1[0] = 1;
_val1[1] = 2;
}
//this is the only method that inherits from class Feature
public override void doSomething()
{
//not implemented yet
}
//this is some other class that does not inherit from Feature
public void doSomethingElse()
{
//not implemented yet
}
}
}
I don't want to instantiate each subclass directly, because there will be a lot of them in the future. I thought I could use the concept of Inheritance to structure my code, because some methodes (here, doSomething()
) exist in all of my classes.
What is the common way to accomplish this? Can anyone show me a best practice?
Thank you!
Upvotes: 1
Views: 87
Reputation: 850
I think the concept you are trying to use is not really inheritance but polymorphism, what you should do is create an object with the type Feature and associate with a new Feature1/2. When you use a method on one of these, it will search the "executive" type first.
Upvotes: 0
Reputation: 2017
instantiateFeature
returns Feature
, which can be either SubFeature1
or SubFeature2
. What if you write SubFeature1 a = myOrga.instantiateFeature("SubFeature2");
? Compiler can't be sure, so it shows you an error. The purpose of such abstract base class is to define some parts which is realy impotant, something enough for you to work without worring which of subclasses you are using right now. So what you do is design such Feature
base class and write code, which uses only Feature
variables.
EDIT, text is too large for comment
Let me show you a little example of what I'm talking about. Imagine we have subfeatures, one of them orders pizza. Now we have subclasses: OrderPizzaByPhoneFeature, OrderPizzaByEmailFeature. Both of their doSomething
order pizza, but in a different way. In our application it is a user setting. Now to order pizza we call instantiateFeature
and pass it "I want to order pizza" or maybe calling instantiatePizzaFeature
. Inside instantiateFeature
looks for settings and decides if it need to create OrderPizzaByPhoneFeature or OrderPizzaByEmailFeature. We get Feature
and call it's doSomething
, which does exactly what we want to do. Now if we want to add some new order type OrderPizzaByPigeonMailFeature
all we need to do is to add user setting and few lines in instantiateFeature
. Ordering code still works fine, it never knew about Feature
subclasses. Well maybe it knew there is some ordering pizza features, but never knew how many of them exist.
Upvotes: 0
Reputation: 292405
The return type of your instantiateFeature
method is Feature
, so if you want to assign it to a SubFeature1
, you need to cast:
SubFeature1 subObj1 = (SubFeature1)myOrga.instantiateFeature("SubFeature1");
SubFeature2 subObj2 = (SubFeature2)myOrga.instantiateFeature("SubFeature2");
But anyway, if you already know the concrete type that the method is going to return, there is no point in using a factory method; you might as well instantiate the concrete class directly. The point of a factory method is usually to abstract the calling code from the actual implementation:
Feature subObj1 = myOrga.instantiateFeature("SubFeature1");
Feature subObj2 = myOrga.instantiateFeature("SubFeature2");
As a side note, in your Organization
class, you should declare obj
as a local variable, not a field. Making it a field means that the instantiateFeature
method is not thread-safe.
Upvotes: 3