Creating new object in abstract class in Java - java

I have two objects which use really similar methods, save for one line. For example:
public class Cat extends Animal
public class Dog extends Animal
And they both use a breed method in the abstract class Animal. One calls new Dog(), and the other new Cat(). Right now I just have it declared as abstract public void breed(); in Animal, but is there a way I can generalize it so I don't have to make it an abstract method to be overridden?

There are many ways to do this, assuming by breed you mean "create children of me."
Reflection
First is to use reflection. If you have a no-args constructor for your classes, this is as easy as calling Class.newInstance:
public Animal breed() {
try {
return (Animal) getClass().newInstance();
} catch (Exception ex) {
// TODO Log me
return null;
}
}
If you don't have a no-args constructor in all your subclasses, you'll have to have a uniform constructor across all your subclasses. For example, if you have Cat(int, String) and Dog(int, String), then you need to get the constructor via Class.getConstructor and invoke newInstance on that:
return (Animal) getClass().getConstructor(int.class, String.class).newInstance(0, "Unnamed");
int and String here may be age and name, for example. This is how you do this with reflection.
Providers
Another way is to use this simple interface:
public interface Provider<T> {
T create();
}
Then have your abstract class take an instance of this in its constructor:
public abstract class Animal {
private final Provider<Animal> animalProvider;
protected Animal( ... , Provider<Animal> animalProvider) {
// ...
this.animalProvider = animalProvider;
}
public Animal breed() {
return animalProvider.create();
}
}
Then your subclasses will pass a Provider<Animal> to the superclass which will create new instances of the subclass:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new DogProvider());
// ...
}
private static class DogProvider implements Provider<Animal> {
public Animal create() {
return new Dog( ... );
}
}
}
Do the same for other subclasses as well.
Note: if by breed you mean "get the type of me," then you should edit your question to say so. If this is what you meant, then this is a viable solution:
public abstract class Animal {
protected final Breed breed;
protected Animal( ... , Breed breed) {
// ...
this.breed = breed;
}
public Breed getBreed() {
return breed;
}
}
I recommend following the get/set conventions for data container methods. Java has bean classes designed to handle these naming conventions, and it's more or less a standard across many platforms. For your subclasses:
public class Dog extends Animal {
public Dog( ... ) {
super( ... , new Breed( ... ));
// ...
}
}

Actually, yes you can. You need to use reflection so performance could be a little iffy, but this (untested) should work:
public abstract class Animal{
public Animal breed(){
return getClass().newInstance();
}
//other methods
}
This will return a new instance of the actual calling type, not the type of Animal (where it's implemented).
This is actually somewhat similar to the Prototype Pattern. Although in this case you're creating a new instance, not copying an existing instance.
Edit
As #FrankPavageau pointed out in the comments, rather than masking an exception in the constructor, you can achieve the same result by using
public abstract class Animal{
public Animal breed(){
return getClass().getConstructor().newInstance();
}
//other methods
}
Which will wrap any exception thrown in an InvocationTargetException which is a bit cleaner and probably easier to debug. Thanks #FrankPavageau for that suggestion.

No there isn't. You will have to have something like what you have done as below
I think you want to have in your abstract class
public abstract Breed getBreed();
and then in each sub class have
public Breed getBreed() {
return new DogBreed();
}
and a similar one returning cat.
or
Have a protected field in the Animal class called breed. This could then be initialised in each of the subclasses. This would remove the need for an abstract method. For example
public abstract class Animal {
Breed breed;
...
}
and then in Dog have
public class Dog extends Animal {
public Dog() {
breed = new DogBreed();
}
}
and have something similar to Cat.
It might be worth you while also passing in the breed to the Dog/Cat ctor so that you can create Dog objects of different breeds rather than restricting your model to just one breed of Dog
I am not sure Breed is necessarily modelled correctly in your example. Do you really want new Dog() to be a breed? Or do you mean type? In which case it is just an animal and the abstract method returning animal is the way to go.

Related

Inherit Properties From Another Class Using Interface Reference

I'm not sure how exactly to phrase my question.
So, I have an interface reference and I'm creating a new object. The new object obviously implements said interface. The initial class inherits another class. That sub-class inherits the super class. However, I cannot access data from super class from the main method without casting the reference first. I'll show an example below
public class a {
public int getSomeData1() {
return someData;
}
}
public class b extends a implements someInterface {
// Some behavior.
}
public class c extends b implements someInterface {
// Some behavior.
}
public class Main {
public static void main(String[] args) {
someInterface obj = new b();
obj.someData1(); // I cannot access someData1().
c anotherObj = new c();
c.getSomeData1(); // This works however.
}
}
How can I have obj.someData1() actually get the data from class a rather than casting it to a.
Just remember the rule that method invocations allowed by the compiler are based solely on the declared type of the reference, regardless of the object type.
If it is not very clear, here is another version of this rule: what is on the left side defines methods you can call, no matter what is on the right :)
Here are a few examples to make it more clear:
public interface Animal {
void voice();
}
public class Dog implements Animal {
public void voice() {
System.out.println("bark bark");
}
public void run() {
// impl
}
}
When you create a dog like this:
Animal dog1 = new Dog();
The reference type which is Animal defines which methods are allowed for you to call. So basically you can only call:
dog1.voice();
When you create a dog like this:
Dog dog2 = new Dog();
The reference type which is Dog, so you are allowed to call:
dog2.voice();
dog2.run();
This rule remains also when you have class inheritance, not only when you implement an interface. Let's say we have something like:
public class SpecialDog extends Dog {
public void superPower() {}
}
And those are examples of what you can call:
Animal dog1 = new SpecialDog();
dog1.voice(); // only this
Dog dog2 = new SpecialDog();
// here you can call everything that Dog contains
dog2.voice();
dog2.run();
SpecialDog dog3 = new SpecialDog();
// here you can call all 3 methods
// this is the SpecialDog method
dog3.superPower();
// those 2 are inherited from Dog, so SpecialDog also has them
dog3.voice();
dog3.run();
In other cases, you need to upcast/downcast to be able to call some specific method.
Happy Hacking :)

How to call default constructor of an abstract class in Java

I tried to research over this topic but could not find a clarity over this. Please help me in this.
In the constructor of a child-class you can call
super(/*params if needed*/);
in order to call its parent's constructor
You can use super() in your child class. You cannot create instance of abstract class(you might know that)
abstract class Parent{
Parent(){
System.out.println("Parent contructor!");
}
}
public class Child extends Parent{
public Child() {
super();
System.out.println("Child contructor!");
}
public static void main(String[] args) {
new Child();
}
}
Even if you do not specify super() in Child class, still the parent class constructor will be called because super() will be put by compiler in default constructor of Child class while generating the .class. If you only have parameterized constructor in Parent class then you will have to explicitly call the parent class constructor by super(..parameter) in your child class constructor . Hope this helps!
Something like this :
abstract class MyClass{
int val;
public MyClass( int val) {
this.val= val;
}
}
class Test extends MyClass{
public Test () {
super(2);
}
}
While you may not call upon a default constructor for an Abastract class, you can invoke the default constructor for the sub-class that embodies your abstract class.
For example:
abstract class Animal {
public Animal (){ ... }
abstract public String sound();
}
class Horse extends Animal{
public Horse(){
super()
}
#Override
public String sound(){
return "neigh";
}
}
class Dog extends Animal{
public Dog(){
super()
}
#Override
public String sound(){
return "woof";
}
}
It is not directly possible to make a new Animal. You can make new Dog-s and Horse-s with annomyously for (common) Type Animal example:
public Animal makeAnimals( Animal existingCreature )
throws InstantiationException, IllegalAccessException
{
return existingCreature.getClass.newInstance();
}
Will make a new instance of the concrete class you provided:
Dog fido = new Dog();
Horse hack = new Horse();
Dog puppy = makeAnimals( fido ); // new uninitialised Dog instance
Horse foal = makeAnimals( hack ); // new uninitialised Horse instance
Alternatively you can make an annomyous instance
Animal parrot = new Animal() {
#Override
public String sound(){
return "squawk";
}
}
As a way to make new animal types. If you were doing something for real like Animals it would probably be better to make a Parot subclass.

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();
}

Work around the need to override abstract methods in Java?

I've been working on an assignment that involves an abstract class that represents a generic animal, with subclasses for cat, dog, reptile, etc. The superclass has abstract methods that aren't actually used by each subclass. For example, there are accessors and mutators for breed and gender that are used by dog and cat but not the reptile class. I personally think this is an odd setup, but it's what is required by the assignment.
At first I tried leaving out the abstract methods not used in a particular subclass, but I quickly found out that leads to an error, due to abstract methods not being overridden. All I had to do to fix that was put in the appropriate methods...
public class Reptile extends Animal
...
public void setBreed(String newBreed){}
public String getBreed(){return null;}
...though it seems to be a bit of a waste seeing as they aren't used. It's not a huge issue, but it made me curious as to whether or not there is an alternative to having to override unused abstract methods in a given subclass. Barring that, is there any convention for what to do when you need to override an abstract method but won't actually be using the method at all?
You have two solutions here.
You can have multiple levels of abstract classes. In other words (these are shell classes and functions...i.e. no code):
public abstract class Animal{
public abstract void fooMethod();
}
public abstract class Pet extends Animal{
public abstract void breed();
public abstract void gender();
}
public class Reptile extends Animal{
public void fooMethod(){}
}
public class Cat extends Pet{ //do the same for Dog
public void fooMethod(){}
public void breed(){}
public void gender(){}
}
This way, Reptile still extends Animal, but you know Reptile doesn't have a breed or gender function, so you don't have to do anything for it. Similarly, Cat and Dog also extend Animal, but now they have breed and gender they must override as well.
Your other solution is to do something like this (the worse of the two solutions):
public class Reptile extends Animal{
public void breed(){
throw new UnsupportedOperationException("Don't call Reptile#breed!!");
}
}
This solution is particularly bad, because if you don't have proper error handling, this exception will propagate all the way up the stack to your main method, and if there is not exception handling for this all the way to your main method, then your program crashes.
I recommend choice A, personally.
Another version of #earchengine's answer, add a couple of interfaces:
public abstract class Animal{
public abstract void fooMethod();
}
public class Breed {...}
public interface Bred {
Breed breed();
}
enum Gender { ...}
public interface Gendered
Gender gender();
}
public class Reptile extends Animal {
public void fooMethod(){}
}
public class Cat extends Animal implements Gendered, Bred {
public void fooMethod(){}
public Breed breed(){}
public Gender gender(){}
}
public class Dog extends Animal implements Gendered, Bred {
public void fooMethod(){}
public Breed breed(){}
public Gender gender(){}
}

ArrayList containing different objects of the same superclass - how to access method of a subclass

Hi I'm wondering if there is a simple solution to my problem,
I have an ArrayList:
ArrayList <Animal> animalList = new ArrayList<Animal>();
/* I add some objects from subclasses of Animal */
animalList.add(new Reptile());
animalList.add(new Bird());
animalList.add(new Amphibian());
They all implement a method move() - The Bird flies when move() is called.
I know I can access common methods and properties of the super class by using this
public void feed(Integer animalIndex) {
Animal aAnimal = (Animal) this.animalList.get(animalIndex);
aAnimal.eat();
}
That's fine - but now I would like to access the move() method the subclass Bird has.
I could do this by casting the Animal as a Bird:
Bird aBird = (Bird) this.animalList.get(animalIndex);
aBird.move();
In my situation I don't want to do this, as it will mean I have 3 different sets of the above code one for each subtype of Animal.
It seems a bit redundant, is there a better way?
There really isn't a nice way to do this from the superclass, since the behavior of each subclass will be different.
To ensure that you're actually calling the appropriate move method, change Animal from a superclass to an interface. Then when you call the move method, you'll be able to ensure that you're calling the appropriate move method for the object you want.
If you're looking to preserve common fields, then you can define an abstract class AnimalBase, and require all animals to build off of that, but each implementation will need to implement the Animal interface.
Example:
public abstract class AnimalBase {
private String name;
private int age;
private boolean gender;
// getters and setters for the above are good to have here
}
public interface Animal {
public void move();
public void eat();
public void sleep();
}
// The below won't compile because the contract for the interface changed.
// You'll have to implement eat and sleep for each object.
public class Reptiles extends AnimalBase implements Animal {
public void move() {
System.out.println("Slither!");
}
}
public class Birds extends AnimalBase implements Animal {
public void move() {
System.out.println("Flap flap!");
}
}
public class Amphibians extends AnimalBase implements Animal {
public void move() {
System.out.println("Some sort of moving sound...");
}
}
// in some method, you'll be calling the below
List<Animal> animalList = new ArrayList<>();
animalList.add(new Reptiles());
animalList.add(new Amphibians());
animalList.add(new Birds());
// call your method without fear of it being generic
for(Animal a : animalList) {
a.move();
}
You dont need to do any casting. The overridden method should get called [simple polymorphism]
Animal aAnimal== this.animalList.get(animalIndex);
aAnimal.move();
Above code should call bird method if object is of bird, isn't it?
And casting is not a solution , how will you decide which object to cast? You will have to use instanceOf.
In your case,the following could work,but time complexity is O(n):
public void moveBird(){
for(Animal aminal:animalList){
if(animal instanceof Bird){
aninmal.move();
}
}
}
Bird getMyBird(Integer aniInteger) {
Bird b = new Bird();
//Do somthig with bird object...
return b;
//get your modifeid bird object
}
Bird myBird = animalList.get(animalIndex);
myBird.move();

Categories