This week's book giveaway is in the OCMJEA forum.
We're giving away four copies of OCM Java EE 6 Enterprise Architect Exam Guide and have Paul Allen & Joseph Bambara on-line!
See this thread for details.
The moose likes Beginning Java and the fly likes making two methods into one Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "making two methods into one" Watch "making two methods into one" New topic
Author

making two methods into one

Kevin Tysen
Ranch Hand

Joined: Oct 12, 2005
Posts: 255
Suppose you have Tiger objects and Dog objects, both subclasses of Animal. You are writing a program that has methods feedTheTigers() and feedTheDogs() and feedOneTiger() and feedOneDog(). Of course, feeding a tiger and feeding a dog are two very different things, and one must go about the tasks totally differently. So you have this code:



In this case, both feedTheTigers() and feedTheDogs() have exactly the same contents, except that they call different methods. In this case, the code which both methods have is quite short, so I don't mind typing it out twice. However, suppose that both methods have a lot of code which is identical, and the only difference between the methods is that one method calls feedOneTiger() and the other method calls feedOneDog(). In that case I want to have that long complicated code only once in my program. One way to do it would be to have a method like this:



But I have a feeling there is a better way.
Christophe Verré
Sheriff

Joined: Nov 24, 2005
Posts: 14687
    
  16

Could inheritance help ? What about a Dog class and a Tiger class ?


[My Blog]
All roads lead to JavaRanch
Ravindra Suroju
Greenhorn

Joined: Mar 11, 2008
Posts: 14
you can use the following code without changing the calling method also no need pass isDog boolean


public void feedTheAnimals(Animal[] animals) {
for (int i = 0; i < animals.length; i++) {
if (animals[i] instanceof Dog) {
feedOneDog(animals[i]);
} else if (animals[i] instanceof Tiger) {
feedOneTiger(animals[i]);
} else {
System.out.println("Generic Animal");
}
}
}

- Ravindra.


Best Regards,<br />Ravindra.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38517
    
  23
There is something not right about that design.

What about a feedTheAnimal(Animal a) method? The variability is in the animals, not the feeder. If you have a zoo, you would not pick up some meat and go wandering round to find which of lions, elephants, hippopotamuses and humming birds eat meat. You would go to the lion, think, "Lions eat meat," then go and fetch some meat.
Similarly you need to get the feeding into the Animal class and its subclasses. That is called polymorphism. You might even have a getFoodType method for each animal. You can store the requisite food in a Map, if you so wish.

It is a general design principle that a class should take care of itself. A Lion object "knows" it eats meat and an Elephant object "knows" it eats grass and twigs. The Feeder class should not have to "know" such things.
Kevin Tysen
Ranch Hand

Joined: Oct 12, 2005
Posts: 255
Thank you for the advice. So what I need to do is to make an Animal class with an abstract method called feedTheAnimal() and then make the Dog class and Tiger class implement the Animal class and have the feedTheAnimal() method. Is that what you are saying? So pass objects to the feedThem() method.



Suppose I have a static method that calculates how much food to feed an animal. The method takes two ints and calculates them a different way.



In this case, the method is a static method, so there is no need to make an object. In the example above, you pass an object to the feedThem method. But in the case of a static method, there is no need to make an object. So is there some way to pass a class to a method?
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38517
    
  23
Something not right about that method which calculates how much the Animal has eaten. That sort of thing is applicable to the Animal object; most animals can remember whether they have eaten recently and whether they are hungry. So you ought to have a field in the Animal class telling you how much it has eaten, and that method ought not to be static.

By the way: multiplying two ints and dividing by 1000 will soon have you returning 0, unless the amounts eaten are ≥ 1000. Why are you not adding? So you can add the amounts eaten; you could even have amounts eaten as an array and shuffle the amounts up every time the animals are fed. Also those method appear very similar, so maybe it should be a fully-implemented method in your abstract Animal class.
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38517
    
  23
You can also have a requiredFood field in each class (that could be static since it will be the same for every instance of the class), and compare the amount fed recently with the Animal's food requirement.
Max Rahder
Ranch Hand

Joined: Nov 06, 2000
Posts: 177
As a rule of thumb, if you see code that checks for the type of an object, then does different actions based on that type, then that code is missing an opportunity to use inheritance and polymorphism. The whole point of these concepts is that the calling routine shouldn't care about the specific type -- the calling routine just says "hey object, do task A in your own way", and the object's implementation of A will do just that.

In your example, you should not say "If it's a tiger, feed it one way, and if it's a panda, feet it another way". Instead, you code should just say "I don't care what kind of animal you are -- I'll just call your feed method, which will be one thing if you're a tiger and a different thing if you're a panda."
Kevin Tysen
Ranch Hand

Joined: Oct 12, 2005
Posts: 255
Thank you all for the advice. What I gather is that I should have different classes which all inherit, override, or implement a feed() method, which can be different for each class, and that my other method can call the feed() method which will behave differently depending on the class of the object passed to the method. Like this:



My methods actually look more like this:



The feed calculation is done only using the int values in foodInfo, so it can be a static method. Also, the Tiger class and Dog class have no fields and no other methods, and the only reason for the existence of those classes is so that I can have two different methods with the same name. Therefore, the feed method and the classes can all be static.

In the example above, an object of type Animal is passed to the method feedTheAnimal. But because the feed method can be static, and the Animal class can be static, there is no reason to make an object. So what I want to know is, instead of passing an object to a method, is it possible to pass just a method to a method? Or is it possible to pass a class to a method? And how is it done?
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38517
    
  23
No, it ought not to be a static method; different zoo keepers may feed different animals.
The info[] is probably in the wrong place. If the info is about a particular animal, then in belongs in the Animal or Tiger class.
The array you want in the ZooKeeper class is an Animal[] array representing the Animals that Keeper takes care of.
Your Animal subclasses ought to override the method; it is probably best to precede the method with the @Override annotation (which will only work in Java5-6).
 
 
subject: making two methods into one