Java: Create particular child class object in Java - java

So let's suppose that I have a class Animal in Java, and 3 child classes. The structure looks like this
class Animal{
...
public breed(){
//create a new child class object here
}
}
class Bird extends Animal{
...
}
class Bear extends Animal{
...
}
class Frog extends Animal{
...
}
I want to create another object in breed class, but I want to create an object of the same child class, from which the method breed() was executed. For instance, if frog.breed() was executed I want to create a new Frog object there (assumming frog is a Frog object), if bear.breed() was executed I want to create a new bear object etc.
Is there any way to handle it in animal class, or I have to override method in every child class?

It's possible if you pass a reference to a function. I suspect method references and passing functions as arguments may be a bit beyond your level right now, but it's not that complicated.
class Animal {
private final Supplier<Animal> ctor;
Animal(Supplier<Animal> ctor) {
this.ctor = ctor;
}
public Animal breed() {
return ctor.get();
}
}
class Bird extends Animal {
public Bird() {
super(Bird::new);
}
}
The advantage of overriding is that Java allows to you make the return type more specific. So if you have a Bird bird; you could do Bird chick = bird.breed();.
class Bird extends Animal {
public Bird breed() { //super return type is Animal, this return type is more specific
return new Bird();
}
}
Without overriding, you can't make the return type more specific, so you would have to assign it to a variable of type Animal chick = bird.breed(), unless you were to cast it.
Also achievable with reflection, but you should avoid it if possible.

Yes, you can do it, using reflection. But this approach isn't recommended, cause it's error-prone and you should consider rather using standard Java inheritance constructions.
Example with recursion:
class Animal{
public Animal breed() throws InstantiationException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
return this.getClass().getDeclaredConstructor().newInstance();
}
}

Related

Abstract class or casting?

I'm trying to figure out whether implementing individual methods of a subclass in an abstract superclass, or casting is the better way to go about the following scenario.
Suppose I have an abstract class Animal which has two subclasses, Dog and Cat and a Main class where I save objects of Dog and Cat in an Animal array. The following is how I would go about using methods of the subclasses in a more generalized array.
class Main{
public static void main(String[] args){
Animal[] animalArray = new Animal[2];
animalArray[0] = new Cat();
animalArray[1] = new Dog();
for (Animal a : animalArray){
if (a.getClass().equals(Dog.class){
((Dog)a).bark();
} else {
((Cat)a).meow();
}
}
}
}
However a friend suggested that casting isn't best practice, and that I should define each method in the abstract superclass in the following way:
public abstract class Animal{
public abstract String meow(){
return null;
}
public abstract String bark();
return null;
}
}
After setting the return values of these methods to null I would need to use #Override and implement them in the respective subclasses.
Which way is better? I'm afraid the abstract class will be too large and will have methods assigned to subclasses that don't make sense (even if all they do is return null). I think by using casting I can make more precise uses of the methods.
meow() and bark() shouldn't be defined in the Animal class. These methods are specific to Cat and Dog classes.
You should define an abstract method as shown below, in the Animal class and override it in the sub classes.
public abstract class Animal {
public abstract String action() {};
}
public class Dog extends Animal {
#Override
public String action() {
//your implementation (bark)
}
}
public class Cat extends Animal {
#Override
public String action() {
//your implementation (meow)
}
}
Hope it answers your query.

Pattern Matching like behavior

I am at a lookout for a design pattern for my simple problem. Here is a simplified version.
class Animal{...}
class Dog extends Animal{...}
class Cat extends Animal{...}
... // so on, 3 other classes as of now
I have a static method (in reality exposed via web-service but its synonymous) which takes an id and returns an animal.
If a cat is returned then the other team using the cat object generates a CatReport. If Dog, then dog report (They can use it for anything). Obviously Cat & Dog have different attributes. Cat and Dog don't have anything else in common apart from the fact that they are Animals. So making a call like below, is insufficient because I need the precise type:
public static Animal getAnimal(int id){}
Not sufficient because animal does not contain all the information what the precise type can give me.
What is the best way to deal with this problem?
PS: In Scala, I would simply do pattern-matching on the object. This solves the problem elegantly.
One solution I have is: make a call which returns an enum signifying what the id corresponds to. And then have a separate call for each:
public static AnimalType getAnimalType(int id){}
public static Cat getCat(int id){}
public static Dog getDog(int id){}
....
But this is cumbersome.
In a language like Java, you can simulate pattern matching behavior using the Visitor pattern.
You can do it in some steps :
Define an interface Animal representing an Animal with a accept method
Add some subclasses to Animal and give the same implementation like in my little example below.
Define an interface Visitor and give it an implementation. This classe will allows to you to simulate some pattern matching on your classes.
Here a little example :
public interface Animal {
public void accept(AnimalVisitor v);
}
public class Dog extends Animal {
public void accept(AnimalVisitor v) {
v.visit(this);
}
}
public class Cat extends Animal {
public void accdept(AnimalVistior v) {
v.visit(this);
}
}
public interface AnimalVisitor {
public void visit(Dog d);
public void visit(Cat c);
}
public class PrintAnimal implements AnimalVisitor {
public void visit(Dog d) {
System.out.println("Dog");
}
public void visit(Cat c) {
System.out.println("Cat");
}
}
Visitor pattern is a elegant way to solve your problem and also it's avoid the accumulation of if (x instance of bar) in one function. With this pattern, your code will be more readable and easier to extend.
The corresponding Scala code to make an idea of my answer:
abstract class Animal {}
case class Dog() extends Animal
case class Cat() extends Animal
object Animal {
def printAnimal(a : Animal) = a match {
case x : Dog => "Dog"
case x : Cat => "Cat"
case _ => "Unknown"
}
def main(args : Array[String]) = {
println(printAnimal(Dog()))
}
}
Well, I don't see any really elegant solution but you can create a kind of report factory with this kind of code
public Report getCorrespondingReport(Animal animal){
if(animal instanceof Dog) return new DogReport();
if(animal instanceof Cat) return new CatReport();
...
...or you could make a generic report and use reflection to inspect your Animal instance and generate your report following general rules but it might not be doable.
If I understand the question correctly, you want to call correct implementation of methods regards of the type of object you have. So if an animal is a cat, generate report method should be called from Cat class if you have code like below
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
First of all as you said,
Obviously Cat & Dog have different attributes. Cat and Dog dont have
anything else in common apart from the fact that they are Animals.
As the subclasses do not have any common functionality, define Animal as an interface instead of a class like given below
interface Animal{
public void generateReport();
}
And create Cat and Dog like this
class Cat implements Animal{
//define cat specific attributes here
public void generateReport(){
//your logic to generate cat report
}
}
class Dog implements Animal{
//define dog specific attributes here
public void generateReport(){
//your logic to generate dog report
}
}
Since the generateReport() method is defined in interface, all the classes implementing the interface must have generateReport().
So when you make a call like this,
public static Animal getAnimal(int id){
//your code to return object of either Cat or Dog
}
animal.generateReport();
the underlying object's method will be called.
If you simply want to know what animal object refers to (returned from getAnimal method i.e. either Cat or Dog), you can check it like below
class Animal{
}
class Dog extends Animal{
public String dogName = "Dog1";
}
class Cat extends Animal{
public String catName = "Cat1";
}
public class HelloWorld{
public static void main(String []args){
//call getAnimal and get the object instead of following line
Animal animal = new Cat();
if ( animal instanceof Cat ){
//cast Animal to Cat
Cat cat = (Cat) animal;
System.out.println(cat.catName);
}else if ( animal instanceof Dog ){
//cast Animal to Dog
Dog dog = (Dog) animal;
System.out.println(dog.dogName);
}
}
}

Accessing Subclass Methods and Instances From Within a Method With A Superclass Parameter

Novice Java programmer here...
So I have this superclass:
public abstract class Animal
{
public abstract String attack(Animal entity);
}
and then I have this subclass:
public class Dog extends Animal
{
protected int something;
public int getSomething()
{
return something;
}
#Override
public String attack(Animal entity)
{
entity.getSomething();
//THIS RIGHT HERE
}
I'm not asking why this isn't working as much as I'm asking how I would go about accessing those methods and instances within that subclass. Should I create a new instance of Dog within the attack method and assign entity to the newly created instance? What is the "right" way to go about accomplishing this?
What you are trying to do is to invoke the method getSomething() on an instance of class Animal in your implementation of the attack(Animal entity) method.
This clearly can't work, because this method is not defined for class Animal. I believe you want that the dog can attack any type of animal and vice versa. What you have to do then is to add the method to the Animal:
public abstract class Animal {
public abstract String getSomething();
//rest
}
Then you clearly have to override the method in every subclass of animal. Or, if possible in your use case, at the attribute to the animal class and implement the getSomething() method directly there:
public abstract class Animal {
private String something;
public String getSomething() {
return this.something;
}
//rest
}
Please think again about the visibility protected of your attribute. If something is protected, than every instance of classes in the same package can access and modify it without the getter.
Dog has an is-a relationship with Animal. This does not go vice versa. Therefore a custom method defined in dog cannot be used in its parent class unless it is an overridden method

Why do we need to override the methods of parent class?

I mean if we want to rewrite all the content of the method in the child class and change its function, why couldn't we just write a new method with a different name? What's the difference? I know this is a simple question. But I am new to programming and very confused. THX.
It's about giving different behaviour to common functionality for that type of thing, for example let's assume all Vehicles beep, but a Car Honk's and a Moped Meep Meeps!
class Vehicle {
public void beep() {
System.out.println("Beep!");
}
}
class Car extends Vehicle {
#Override
public void beep() {
System.out.println("Honk!");
}
}
class Moped extends Vehicle {
#Override
public void beep() {
System.out.println("Meep Meep!");
}
}
That's called Polymorphism. Have a look at the link.
A simple example is the Java Collections framework. You have an interface List when you are using it. You don't want to know how add or size is working. It should just work.
But when you are on the implementation side there are differences for ArrayList or a LinkedList in the way how they manage the items, that where stored in there.
When you look at already implemented methods in super classes, you might need one method to have a different behavior. Now pretend you have some method calls in your current code. If you don't want them to change, so you just override that method and the client does not have to change his code in order to use your functionality.
Overriding is a feature that is available while using Inheritance.
It is used when a class that extends from another class wants to use most of the feature of the parent class and wants to implement specific functionality in certain cases.
class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
}
class Cat extends Animal{
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
Animal c = new Cat(); // Animal reference but Cat object
a.move();// runs the method in Animal class
b.move();//Runs the method in Dog class
c.move();//Runs the method super method
}
}
So by using a parent class you dont need to define move() in each of class that extends animal you can override it wherever necessary.

How to wrap different type of object in one single wrapper object

i have a condition where i need to use a fixed Method signature which may accept different type of object. one solution i think is to use a super class and let all as a subclasses. however is there any good elegant design pattern kind of solution where we solve this
also once method gets an object of certain type can we know the type of instance without instanceof check ?
please suggest.
Your question is a little bit vaque, and can be interpreted in two different ways:
Implementing different behavior in one class
Let's assume you have two different classes: Cat and Dog. Then you have a class Animals and want to do something like this:
Cat cat = new Cat();
Dog dog = new Dog();
Animals animals = new Animals();
animals.feed(cat);
animals.feed(dog);
Here feed() executes different code, depending on the parameter type:
public class Animals {
public void feed(Cat cat) {
// ... feed the cat
}
public void feed(Dog dog) {
// ... feed the dog
}
}
This is called method overloading.
Implementing different behavior in different classes
On the other hand, you could define an interface Pet which provides a method, let's say eat():
public interface Pet {
void eat();
}
Then Cat and Dog should implement Pet to get different behavior:
public class Cat implements Pet {
public void eat() {
//...
}
}
public class Dog implements Pet {
public void eat() {
//...
}
}
Then your class Animals would look like this:
public class Animals {
public void feed(Pet pet) {
pet.eat();
}
}
Implementing an interface is a better pattern than inhering a super class. in that way your classes retain their one-inheritance capacity.
regarding the other question about instanceOf, there is rarely a genuine need to determine the actual class of the object. you can always resort to polymorphism. put all methods that you need to invoke on the object in the interface itself. in that way you will never need to know the actual type.

Categories

Resources