MrHen
MrHen

Reputation: 2480

How to get this.getClass().getConstructor of a super class?

Is there a way for me to get a super implementation directly through getContructor? I want to call the constructor on "this class or any superclass".

The scenario details are that I have a base class that builds its data using reflection but the data is coming in from an external file. The external loader has a lookup that checks to see if data exists for a particular class and all of that is wrapped into ImplementedCard, below.

This works fine (enough) and isn't directly related to the question aside from my needing to be able to create all of these instances starting from an ImplementedCard instance:

public class Card implements DeepCopyable<Card> {
   protected ImplementedCardList.ImplementedCard implementedCard;

   public Card() {
        this.implementedCard = ImplementedCardList.getInstance().getCardForClass(this.getClass());
        this.initFromImplementedCard(this.implementedCard);
    }

    public Card(ImplementedCardList.ImplementedCard implementedCard) {
        this.implementedCard = implementedCard;
        this.initFromImplementedCard(this.implementedCard);
    }

    public void initFromImplementedCard(ImplementedCardList.ImplementedCard implementedCard) {
        if (implementedCard != null) {
            this.name_ = implementedCard.name_;
            /* ... and so on */
       }
    }

    // This deepCopy pattern is required because we use the class of each card to recreate it under certain circumstances
    @Override
    public Card deepCopy() {
        Card copy = null;
        try {
            try {
                copy = this.getClass().getConstructor(ImplementedCardList.ImplementedCard.class).newInstance(this.implementedCard);
            } catch(NoSuchMethodException e) {
                if(!this.getClass().equals(TestHero.class)) {
                    log.warn(this.getClass().toString() + " is missing ImplementedCard constructor");
                }
                copy = getClass().newInstance();
            } catch(InvocationTargetException e) {
                log.error("InvocationTargetException error", e);
                copy = getClass().newInstance();
            }
        } catch(InstantiationException e) {
            log.error("instantiation error", e);
        } catch(IllegalAccessException e) {
            log.error("illegal access error", e);
        }
        if (copy == null) {
            throw new RuntimeException("unable to instantiate card.");
        }

        copy.name_ = this.name_;
        /* ... and so on */

        return copy;
    }
}

This base class is then extended like so:

public class Minion extends Card implements CardEndTurnInterface, CardStartTurnInterface {
    public Minion() {
        super();
    }

    public Minion(ImplementedCardList.ImplementedCard implementedCard) {
        super(implementedCard);
    }

    @Override
    public void initFromImplementedCard(ImplementedCardList.ImplementedCard implementedCard) {
        if (implementedCard != null) {
            super.initFromImplementedCard(implementedCard);

            /* custom init goes here */
        }
    }

    /* other class details follow */
}

public abstract class Hero extends Minion implements MinionSummonedInterface {
    public Hero() {
        super();
    }

    public Hero(ImplementedCardList.ImplementedCard implementedCard) {
        super(implementedCard);
    }

    /* no custom init; other class details follow */
}

public class Hunter extends Hero {
    public Hunter() {
        super();
    }

    public Hunter(ImplementedCardList.ImplementedCard implementedCard) {
        super(implementedCard);
    }

    /* no custom init; other class details follow */
}

This goes on for hundreds of classes. What I want to do is pull out the constructors that do nothing but call super with the same parameters but when I do, it breaks the getConstructor call in deepCopy.

Upvotes: 0

Views: 1943

Answers (2)

nhylated
nhylated

Reputation: 1585

For each class, you can do:

Hero h = new Hero();
Class hc = h.getClass();

// Get super class and its constructor.
Class<?> sc = hc.getSuperclass();
Constructor scConst = sc.getConstructor(ImplementedCard.class);

// Get super class's parent and its constructor.
Class<?> ssc = sc.getSuperclass();
Constructor sscConst = ssc.getConstructor(ImplementedCard.class);

You could also put this in a loop until you get to Object.class or some other point in the class hierarchy where you'd like to break.

Upvotes: 2

Ravindra HV
Ravindra HV

Reputation: 2608

As @nhylated suggested, try

this.getClass().getSuperClass()

Here is a nice explanation regarding why

super.getClass()

behaves like it does.

Upvotes: 1

Related Questions