Pass class type that subclass or implements class; then access static methods & create instances of that type; is it possible in Java, and how?

27 views Asked by At

To achieve polymorphism and reusability of code; is it possible to pass to a method some Java construct that represents a class type that extends super class (possibly abstract but not necessarily) then that method detects the class type dynamically and can invoke its static methods and instantiate instances of it?

Following code is not runnable, but just a map/blueprint to convey my imagination of what I want to explain.

What matters most is explained in the classes Animal and Zoo down, and more explanation in comments, however I am not confined to the specified structure of interface or superclass, just I want to achieve code reusability preferably by polymorphism, and not through reflection (if possible) and not through checks of instanceof within switch / else-if statements, hence; dynamic resolution.

AnimalInterface:

public interface AnimalInterface {

    public String getNameInstanceMethod();

    public void setNameInstanceMethod(String name);

}

Animal:

public abstract class Animal implements AnimalInterface {

    /**
     * @return instance of class that extends Animal
     */
    public static Animal getNewInstance(){
        // Is it possible to implement it to return an instance
        // of a type which extends this Animal abstract class
    }
}

Dog:

public class Dog extends Animal {

    private static final String DB_ENTITY = "dogs";
    private String name;
    
    public static String getDB_entity_by_staticMethod(){
        return Dog.DB_ENTITY;
    }

    @Override
    public String getNameInstanceMethod() {
        return name;
    }

    @Override
    public void setNameInstanceMethod(String name) {
        this.name = name;
    }
}

Cat:

public class Cat extends Animal {
    
    private static final String DB_ENTITY = "cats";
    private String name;
    
    public static String getDB_entity_by_staticMethod(){
        return Cat.DB_ENTITY;
    }

    @Override
    public String getNameInstanceMethod() {
        return name;
    }

    @Override
    public void setNameInstanceMethod(String name) {
        this.name = name;
    }
}

Zoo

public class Zoo {

    /**
     * The passed argument (AnimalClassType) to processAnimalDetails() must NOT
     * be instance, but just type such as Dog.class or Cat.class, or whatever
     * Java construct that conveys class that extends Animal without creating
     * dummy instance so that Java dynamically detect the subclass without
     * reflection (if possible) and without instanceof checks within switch / else-if
     * statements.
     */
    public static void processAnimalDetails(/*AnimalClassType*/) {
        /**
         * AnimalClassType determined dynamically at run time; If method
         * argument was Dog.class then method returns "dogs", If method argument
         * was Cat.class then method returns "cats".
         */
        String dbEnitiyName = AnimalClassType.getDB_entity_by_staticMethod();
        // dbEnitiyName can be used to retrieved from db table
        String animalNamefromDatabase = "Name retrieved from database";
        // Since AnimalClassType will be determined at run time;
        // If method argument was Dog.class, then animalInstance with be instance of Dog class
        // If method argument was Cat.class, then animalInstance with be instance of Cat class
        Animal newAnimalInstance = AnimalClassType.getNewInstance();
        newAnimalInstance.setNameInstanceMethod(animalNamefromDatabase);
    }
}

Main

public class Main {

    public static void main(String[] args) {
        /**
         * Pass Dog.class or whatever Java construct that conveys class that extends Animal
         * without creating dummy instance, so that we access static methods of the class
         * and create instances of it.
         */
        Zoo.processAnimalDetails(Dog.class);
    }
}
1

There are 1 answers

0
tgdavies On

Create a factory interface:

interface AnimalFactory {
  String getDbEntityName();
  Animal createInstance();
}

With implementations for Dog and Cat:

class DogFactory implements AnimalFactory {
 ...
}

Then your main method is:

Zoo.processAnimalDetails(new DogFactory());

And processAnimalDetails is:

public static void processAnimalDetails(AnimalFactory factory) {

        String dbEnitiyName = factory.getDBEntityName();
        String animalNamefromDatabase = "Name retrieved from database";
        
        Animal newAnimalInstance = factory.getNewInstance();
        newAnimalInstance.setNameInstanceMethod(animalNamefromDatabase);
    }