Create an array of superclasses while maintaining polymorphic attributes - java

If I had an array of Birds that is filled during run-time, how can I access member methods specific to child classes?
class Bird
{
public Bird() {}
public void fly(int x) {
System.out.println("Flew "+x+" meters");
}
}
class DumbBird extends Bird
{
public DumbBird() {super();}
public void fly(int x) {
x-=5; //we're dumb
System.out.println("Flew "+x+" meters");
}
public void sing() {
System.out.println("La la la!");
}
}
public static void main(String[] args)
{
Bird[] cage = new Bird[10];
cage[0] = new Bird();
cage[1] = new Dumbbird();
cage[2] = new Sleepybird();
//.... more bird types
cage[1].sing(); //is inaccessable because it is of type Bird not DumbBird!
}
Is there a good way to be able to have a an array of generic types while being able to access member functions specific to a child class? I would like to not have to edit the Bird class.

In theory, yes. Items put in arrays are reifiable, so you could determine which type you're looking at and cast the particular object to it's actual type. This isn't a very clean solution, though, so I wouldn't recommend it.
You may consider having an abstract class or interface representing bird that has methods most birds would support, along with a check method canSing() or canFly(). Birds that don't support this such as flightless birds can throw an UnsupportedOperationException if you try to call a method the bird doesn't support, but there is no easy way to generically reference all of the birds and know about all of the different methods each sub-type of bird can have.

Just to remove my answer from the comments.
Switch to using lists instead of arrays and when you pull your specific bird out, you will need to cast it to the correct type of "Bird", see the below code example:
import java.util.ArrayList;
class Bird
{
public void fly(int x) {
System.out.println("Flew "+x+" meters");
}
}
class DumbBird extends Bird
{
public void fly(int x) {
x-=5; //we're dumb
System.out.println("Flew "+x+" meters");
}
public void sing() {
System.out.println("La la la!");
}
}
class Test {
public static void main(String[] args) {
ArrayList<Bird> cage = new ArrayList<Bird>();
cage.add(new Bird());
cage.add(new DumbBird());
cage.add(new Bird());
cage.add(new DumbBird());
cage.add(new SleepyBird());
((DumbBird) cage.get(1)).sing();
}
}

Related

What is the difference between these two codes regarding interface?

I am currently learning java. I just don't understand the use of interface and I am really confused about it.
These two codes return the same answer, then what is the use of interface here?
interface Jumpable {
abstract int maxDistance();
}
class Animal implements Jumpable {
public int maxDistance() {
return 100;
}
}
public class Forest {
public static void main(String args[]) {
Animal lion = new Animal();
System.out.println(lion.maxDistance());
}
}
class Animal {
public int maxDistance() {
return 100;
}
}
public class Forest {
public static void main(String args[]) {
Animal lion = new Animal();
System.out.println(lion.maxDistance());
}
}
In the state your code is in right now, there is no difference, but that is not what it is about. Further down the line you will need to do things with your animals, without knowing what animals you have or what they can do.
Suppose you want to subclass your animals, into mammals, birds and insects. Some of them can jump, but not others. It will be very ugly code if you create specific classes or attributes for mammals that can jump etc. If you instead create an interface, you have lots of options. You can create a list of animals that can jump, and then tell them to jump, regardless of their type.
Later, you might want to add screaming to your animals. Just add an interface for that.

How to get rid of instanceof check when using inheritance?

Assume we have a class Animal, with subclasses as cat, eagle
Now I have a method:
public void process(Animal animal) {
if (animal instanceof Cat) {
if (!animal.meow()) {
throw exception("cat does not meow");
} else {
animal.feedFish();
}
}
if (animal instanceof eagle) {
if (!animal.fly()) {
throw exception("eagle does not fly");
} else {
animal.checkMaxFlightAltitude();
}
}
}
Here cat has 2 methods meow and feedfish which are completely different than eagle's methods fly and checkmaxflight
Most design patterns revolve around assumptions that subclasses have a common method like Shape draw() inherited by circle draw and square draw
Is there some way to do validations on subclasses, such as cat and eagle without instanceof check ?
Any good design pattern ( assuming subclasses dont share a method in base class ? )
You could have an abstract process method in Animal and implement it in the subclasses:
class Animal {
protected abstract void process();
public static void process(Animal a) { a.process(); }
}
class Cat {
void process() {
if (!meow()) throw exception("cat does not meow");
else feedFish();
}
public boolean meow() { ... }
public void feedFish() { ... }
}
You could use double dispatch by employing a visitor.
Example:
public class Animal {
public abstract void accept(AnimalVisitor v);
public boolean meow() {return false;}
public boolean fly() {return false;}
public void feedFish() {};
public void checkMaxFlightAltitude() {};
}
public class Cat extends Animal {
public void accept(AnimalVisitor v) {
v.visitCat(this);
}
public boolean meow() {return true;}
}
public class Eagle extends Animal {
public void accept(AnimalVisitor v) {
v.visitEagle(this);
}
public boolean fly() {return true;}
}
public interface AnimalVisitor {
void visitEagle(Eagle eagle);
void visitCat(Cat cat);
}
public class AnimalVisitorExample implements AnimalVisitor {
public void visitEagle(Eagle eagle) {
eagle.checkMaxFlightAltitude();
}
public void visitCat(Cat cat) {
cat.feedFish();
}
}
Animal animal = new Cat();
animal.accept(new AnimalVisitorExample());
(1) Is there some way to do validations on subclasses, such as cat and eagle without instanceof check ?
yes, there is. You could define a "validate" method (abstract in "Animal" class) and implement it in the specific subclasses. Depending on the validation result (e.g. exception / problem list) you can have the validate method throw some kind of "InvalidContentException" or provide the method call with an "ErrorHandler" that is informed about the bad things of an instance.
(2) assuming that the subclasses don't share a method in the base class: well, that one is a bit counter intuitive. On one hand you want to be able to do something on an "Animal", yet you don't want to define that capability on it?
You could define a Validator class that has separate validation methods (on for each kind of "Animal" subclass). That would eliminate the instanceof checks, however you would never be able to pass this Validator class other "Animals" (such as "Dog"), only "Cat" and "Eagle" (or subclasses thereof). You might also want to consider what you want to happen when passing subclasses of "Cat": are all sublasses of Cat validated in the same way or is there subclass specific behavior (like color, size, ...) for the different cat classes?
--> I think you should ask yourself if you want to be able to validate animals in general. Without having insight into your problem domain (which might have reasons not to do it), I'd recommend to have a "validate" method on the animal. You could also go for a visitor pattern, but that requires the Animal to have a "accept(AnimalVisitor visitor)" method and is slightly more code to write (presumably more than you want to)
This is when polymorphism comes in handy.
abstract class Animal {
abstract public void process(Animal animal);
}
class Cat extends Animal {
#Override
public void process(Animal animal) {
if (!this.meow()) {
throw exception("cat does not meow");
} else {
this.feedFish();
}
}
}
class Eagle extends Animal {
#Override
public void process(Animal animal) {
if (!this.fly()) {
throw exception("eagle does not fly");
} else {
this.checkMaxFlightAltitude();
}
}
}

Create a dynamic class in java

I'm working on a problem where different animal types implement the same talk() method from Animal interface.
If you look at getAnimal() method, you can see that, when a new kind of animal is added to the program, inside of that method has to be changed as well.
I want to add new animals just by subclassing Animal without changing anything in the already existing classes.
For example, add an animal "Dog", criteria="loyal"; talk="woof".
Could you tell me, how it is possible? Below is my code:
interface Animal {
public void talk();
}
class Lion implements Animal {
#Override
public void talk() {
System.out.println("ROARRRRR");
}
}
class Mouse implements Animal {
#Override
public void talk() {
System.out.println("SQUEEEEEAK");
}
}
class Bison implements Animal {
#Override
public void talk() {
System.out.println("BELLOWWWWW");
}
}
class AnimalType {
public static Animal getAnimal(String criteria) {
// I refactor this method
if (criteria.equals("small")) {
return new Mouse();
} else if (criteria.equals("big")) {
return new Bison();
} else if (criteria.equals("lazy")) {
return new Lion();
}
return null;
}
}
public class AnimalExamples {
public static void main(String[] args) {
AnimalType.getAnimal("small").talk();
AnimalType.getAnimal("big").talk();
AnimalType.getAnimal("lazy").talk();
// how to add an animal "Dog" here, criteria="loyal"; talk="woof"
AnimalType.getAnimal("loyal").talk();
try {
AnimalType.getAnimal("small").talk();
} catch (Exception ex) {
System.out.println("Animal does not exists");
}
}
}
I searched on google, understood it can be done by reflection. But do not know how. If possible, could you help me with this, please? Thanks in advance!
Just so you know runtime class generation is extremely complex and not something recommended for beginners to the language. This would be an excellent scenario to use a map an anonymous classes.
class AnimalType {
private static final Map<String, Animal> animals = new HashMap<String, Animal>();
static {
// Populating map with default animals
addAnimal("big","BELLOWWWWW"); // bison
addAnimal("small","SQUEEEEEAK"); // mouse
addAnimal("lazy","ROARRRRR"); // lion
addAnimal("loyal","WOOF "); // dog
}
public static void addAnimal(String criteria, final String sound) {
// Assigning a anonymous implementation of animal to the given criteria
animals.put(criteria, new Animal() {
#Override
public void talk() {
System.out.println(sound);
}
});
}
public static Animal getAnimal(String criteria) {
// Returning an animal from the animals map
return animals.get(criteria);
}
}
If you really do insist on true runtime class generation or if you're curious how it works, check out ByteBuddy.
Old question, but here is how to create class... For me the easy way is to use Javassist.
I created a small example here: http://hrabosch.com/2018/04/08/generate-class-during-runtime-with-javassist/
But here is main point:
public static Class generateClass(String className, String methodName, String methodBody)
throws CannotCompileException {
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.makeClass(className);
StringBuffer method = new StringBuffer();
method.append("public void ")
.append(methodName)
.append("() {")
.append(methodBody)
.append(";}");
cc.addMethod(CtMethod.make(method.toString(), cc));
return cc.toClass();
}
So what I did... Via Javassist I made a class in ClassPool. Also I added a method inside this class and via reflection I invoked it.
Hope it helps.
Just keep on mind whatever you want to use in generated class, there
are NOT imports, so you have to use fully-qualified names.
Java doesn't support creating a class at runtime. However there are really better ways of achieving what you want here. I'll propose two.
Firstly, you could create an AnimalType class that contains all the shared behaviour about a species. You could then have an Animal class that takes an AnimalType as a constructor parameter.
Secondly, you could use a prototype design pattern. In this case the Animal class would need a clone method to create a new animal from the prototype. The factory class could then have a list of the prototypes and use whatever logic you desire to choose the correct prototype to clone.
Comment below if you want further details or sample code for either of these options.
you have to define the dog class
class Dog implements Animal {
#Override
public void talk() {
System.out.println("woof");
}
}
and add the if else to AnimalType
} else if ("loyal".equals(criteria)) {
return new Dog();
}

Class object as List's type

I have class Animal and two subclasses Tiger and Eagle. Both of subclasses have hunt method which is pretty much the same. The only difference between them is type of Victims. Method hunt is using generic class Field<T> for seekeing victims. It looks like this:
Tiger
void hunt(){
Field<Cattle> field = new Field<Cattle>();
List<Cattle> list = field.getObjects();
...
Eagle
void hunt(){
Field<Rabbit> field = new Field<Rabbit>();
List<Rabbit> list = field.getObjects();
...
Is there any way to perform something like that?
void hunt(Object type){
Field<type> field = new Field<type>();
List<type> list = field.getObjects();
I know that I can get list full of Object type and use instanceof later, but here we come to second question:
Is it possible to call if( object instanceof instanceOfSomeClass)?
You can use generics to achieve what you want:
public class AnimalsGenerics<E> {
public void Hunt(E prey){
...
}
}
and implement your animals specifying the prey:
public class Tiger extends AnimalsGenerics<Buffalo> {
}
But my personal implementation would be using interfaces to specify what does the animal do, for example: what happens if the animal is not a hunter, for example an herbivorous, would you need to implement your animal class again? follow the principle of leaving the implementation to the interfaces and not the heritance would help you to have a cleaner code, my dessign would be:
To design the behaviour:
public interface CollectFoodBehaviour<E> {
void collectFood(E prey);
}
Class animal would be:
public class Animal<E> {
CollectFoodBehaviour<E> collectFoodBehaviour;
public void goToGetFood(E food){
collectFoodBehaviour.collectFood(food);
}
}
Implementing the hunting behaviour:
public class HuntAnimalsBehaviour<E> implements CollectFoodBehaviour<E> {
#Override
public void collectFood(E prey) {
//implemenet the generic hunting process
}
}
and an animal instance as an example:
public class Dog extends Animal<Rabbit> {
public Dog(){
this.collectFoodBehaviour = new HuntAnimalsBehaviour<Rabbit>();
}
}
Is it possible to call if( object instanceof instanceOfSomeClass)?
No, instanceof tests if an object is an instance of a class, not an instance of an instance (as if the left side is a non-static reference and the right side is static reference); You can, however, not declare your instance
// JButton b = new JButton();
// if (b instanceof Component) can be replced with
if (JButton.class.newInstance() instanceof Component)
// or
if (new JButton() instanceof Component)
if for some odd reason you find this useful.
If I understood correctly, you can use a generic method using following code:
If you pass the object class, not the instance, you can construct a Field instance using the Class passed as parameter.
public class MyAnimal {
public <T> void hunt(Class<T> type) {
Field<T> field = new Field<>();
List<T> list = field.getObjects();
if (type == Cattle.class) {
System.out.println("Type is a Cattle");
} else {
System.out.println("Type is not a Cattle, is a " + type.getName());
}
}
public static void main(String[] args) {
new MyAnimal().hunt(Cattle.class);
new MyAnimal().hunt(new Cattle().getClass());
}
}
About your second question, if you have the Class type, you can ask with a simple: type == MyClass.class.

Avoid using instanceOf in observer method

I have the following system in Java:
public class Human {
public void drown(Animal animal) {
if (animal instanceOf Fish) {
return;
} else {
animal.die();
}
}
}
public abstract class LandAnimal extends Animal{...}
public class Tiger extends LandAnimal{...}
public abstract class Fish extends Animal {...}
public class Trout extends Fish {...}
I have thought of adding a method
public abstract boolean drownable() {...}
in class Animal but I don't have access to the code of Animal class.
As I know the use of instanceOf is considered bad OOP practice. How do I avoid the use of instanceOf in this case? Thanks.
The drown() method in Human should be (by the way, why do humans want to drown animals?):
public void drown(Animal animal) {
animal.drown();
}
And each Animal will know what to do, for example:
// in class Tiger
public void drown() {
die();
}
// in class Fish
public void drown() {
// do nothing, fish can't drown
}
You would declare Animal.drown() and override it in Fish, containing the appropriate 'kill code' :).
So you'd just need to call drown() on each animal and each instance will behave according to its type specific method implementation.
public class Human {
public void drown(Animal animal) {
animal.drown();
}
}
Methods can be overloaded based on their arguments. You can have two different methods:
public void drown(Fish f) {
return;
}
public void drown(LandAnimal a) {
a.drown();
}
However, it should be noted that this makes determining whether some animal will drown the responsibility of the Human class, which, as other answers show, is arguable.

Categories