hakuna matata
hakuna matata

Reputation: 3327

Cast an object to class type passed as parameter

I have a parent class and 2 child classes. I am trying to implement a function that takes the type of the child and which child as parameters.

When I use child.newInstance(), I want to store it in a variable of the type that is passed and call a function from the second parameter.

Below are the classes

public class Parent {
    public void test() {
        System.out.println("Test from parent");
    }
}

public class ChildA extends Parent {
    public void testChildA() {
        System.out.println("Test from child a");
    }
}

public class ChildB extends Parent {
    public void testChildB() {
        System.out.println("Test from child b");
    }
}

and here is the method I'm trying to implement

public class Driver {
    Parent func(Class child, String whichChild) throws Exception {
        // whichChild: "ChildA" or "ChildB"

        Object obj = child.newInstance();
        // cast obj to type of child and call the method "test" and "test" + whichChild
    }
}

Can it be done what I am trying to do? If yes, how can I cast this object to the type that is passed?

Upvotes: 14

Views: 30976

Answers (4)

Discern
Discern

Reputation: 183

Try this one.

public class Driver {
    Parent func(Class child, String whichChild) throws Exception {
        // whichChild: "ChildA" or "ChildB"

        child.forName(whichChild);

        Object obj = child.newInstance();
        // cast obj to type of child and call the method "test" + whichChild
    }
}

Upvotes: 0

Andy Turner
Andy Turner

Reputation: 140328

If you add a constraint to child, you don't need a cast at all to get a Parent:

Parent func(Class<? extends Parent> child, String whichChild) throws Exception {
    // whichChild: "ChildA" or "ChildB"

    Parent obj = child.newInstance();
    //...
}

However, you still can't call the testChildA etc method, since all you have is an instance of Parent. You'd need to use reflection to get the method:

Method method = obj.getClass().getMethod().getMethod("test" + whichChild);
method.invoke(obj);

It would be better to have a method on the interface of Parent which you can invoke, and is overridden in the subclasses.

public abstract class Parent {
  public void test() {
    System.out.println("Test from parent");
  }

  public abstract void testChild();
}

then simply call:

obj.testChild();

or, as Emanuele Ivaldi points out, just override test in ChildA and ChildB and invoke that directly.

Upvotes: 6

lance-java
lance-java

Reputation: 27984

Not sure exactly what you're doing but you can use Class.cast(...).

Eg

public <T> T getInstance(Class<T> type) {
    Object o = type.newInstance();
    T t = type.cast(o);
    return t;
}

Upvotes: 21

Stultuske
Stultuske

Reputation: 9437

I doubt it. As far as the compiler concerns, any instance of Class can be sent as parameter.

So, for the compiler, there is no proof that this instance is actually an instance of the type you send along.

Upvotes: -1

Related Questions