SnakeDoc
SnakeDoc

Reputation: 14351

Generics Map - avoid numerous casts

I have:

public abstract class Report {
    protected Map<String, Transaction> m = new HashMap<String, Transaction>();
    // more stuff
}

.

public class TRRTransaction extends Transaction {
    public String someMethodOnlyInTRRTransaction() {
        // do stuff
    }

    @Override
    public void someInheritedMethod() {
        // do stuff
    }
    // more stuff
}

.

public class TRRReport extends Report {
    public void doSomething() {
        for (B b : m.values()) {
            query.setString(1, ((TRRTransaction) b).someMethodOnlyInTRRTransaction());
        }
    }
    // more stuff
}

I am trying to avoid having to explicitly cast into TRRTransaction all over the place. In my case, TRRReport will only ever be dealing with TRRTransaction in it's inherited HashMap. There are other types of Report subclassess, each deals with only it's related-type Transaction. Other than removing the HashMap from Report and moving it down locally into each subclass of Report, I'm not sure what else can be done.

I had a similar question, but I think I may have asked in the wrong way and didn't get a straight answer out of it: HashMap using Generics

Upvotes: 0

Views: 51

Answers (2)

rgettman
rgettman

Reputation: 178253

You could make your Report class generic, with an upper bound of Transaction.

public abstract class Report<T extends Transaction> {
   protected Map<String, T> m = new HashMap<String, Transaction>();

Then the subclass TRRReport can define T to be TRRTransaction:

public class TRRReport extends Report<TRRTransaction> {
    public void doSomething() {
        for (TRRTransaction b : m.values()) {
            query.setString(1, b.someMethodOnlyInTRRTransaction());
        }
    }
    // more stuff
}

Upvotes: 4

SLaks
SLaks

Reputation: 887305

You need to make your classes generic:

public abstract class Report<T extends Transaction> {
    protected Map<String, T> m = new HashMap<String, T>();
    // more stuff
}

public class TRRTransaction extends Transaction {
    public String someMethodOnlyInTRRTransaction() {
        // do stuff
    }

    @Override
    public void someInheritedMethod() {
        // do stuff
    }
    // more stuff
}

public class TRRReport extends Report<TRRTransaction> {
    public void doSomething() {
        for (B b : m.values()) {
            query.setString(1, b.someMethodOnlyInTRRTransaction());
        }
    }
    // more stuff
}

Upvotes: 5

Related Questions