Simple Object Oriented Programming Concepts
it may look like a bogus question to you, but I'm having difficulty with this:
We have abstract class Animal
u Cat
and u Dog
that extend it. In Animal
we have a method produceSound();
that is abstract. As you might guess, for Cat
he must return "Mao" and for Dog
"Bao" or something like that. This is fine, but now we have to write a method static
in Animal class
that returns objects Cat
or Dog
depending on their sound. For example: identifyAnimal("Mao")
should return Cat
.
Question : How to implement the method identifyAnimal(String sound)
?
Here are some simple examples of hierarchy:
Animal class
public abstract class Animal {
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
// TODO
}
}
Cat class
public class Cat extends Animal{
@Override
protected String produceSound() {
return "Mao";
}
}
Dog class
public class Dog extends Animal{
@Override
protected String produceSound() {
return "Bao";
}
}
Test class
public class AnimalTest {
public static void main(String[] args) {
Animal.identifyAnimal("Bao");
}
}
In the class, AnimalTest
when called, Animal.identifyAnimal("Bao");
we must get Dog
.
source to share
private static Class[] animalTypes = [Dog.class, Cat.class];
public static String identifyAnimal(String animalSound)
{
for (int i = 0; i < animalTypes.length; i++) {
Animal a = animalTypes[i].newInstance();
String s = a.produceSound();
if (animalSound.equals(s))
return animalTypes[i].getName();
}
return null;
}
source to share
So here's a (terrible) way to do it. I actually jerked a little. I don't know which language you are using, so I am going with C ++ (sorry current mode), although you can replace maps with dictionaries if we are in C #, no matter. This is a bad way of doing things, but should work (conceptually, anyway)
Again ... Terrible ...
public abstract class Animal {
protected abstract String produceSound();
protected static map<string, string> SoundList;
protected static bool registerSound(string sound, string type)
{
return (SoundList.insert( pair<string, string>(sound, type)))->second;//true if worked false if already there
}
protected static string identifyAnimal(string animalSound)
{
map<string,string>::iterator result = SoundList.find(sound);
if(result != SoundList.end())
return result->second;
else
return "What The Hell Is This!?";
}
}
Cat class
public class Cat extends Animal
{
Cat()
{
Animal::registerSound("Mao","Cat");
}
@Override
protected String produceSound() {
return "Mao";
}
}
source to share
abstract class Animal {
static Map<String,String> map = new HashMap<String,String>();
public Animal(String value) { map.put(produceSound(), value); }
protected abstract String produceSound();
protected static void identifyAnimal(String animalSound) {
System.out.println(map.get(animalSound));
}
}
class Cat extends Animal {
@Override
protected String produceSound() { return "Mao"; }
Cat(){ super("CAT"); }
}
class Dog extends Animal {
@Override
protected String produceSound() { return "Bao"; }
Dog(){ super("DOG"); }
}
class Test {
public static void main(String[] args) {
new Dog();
new Cat();
Animal.identifyAnimal("Bao");
}
}
source to share
You can use reflection to get a list of all types that extend Animal, loop through them with an Activator to instantiate each type, doing workSound on each until you find a return value that matches animalSound, returning that instance. Slow but effective when you want your animal class not to know what is extending it.
source to share
What is the nature of the problem you are trying to solve? There is no "right" way that does not depend on the problem.
What is required for the consumer application out of class Animal
? What should your application do with the classes it consumes? Nothing can be accepted if these presumptions are not clear.
source to share