Java erasure with generic overloading (not overriding)

12,318

Solution 1

Either rename the methods, or use polymorphism: use an interface, and then either put the clawback code in the objects themselves, or use double-dispatch (depending on your design paradigm and taste).

With code in objects that would be:

public interface Clawbackable{
    void clawBack()
}


public class CommissionFacade
{

    public <T extends Clawbackable> void clawBack(Collection<T> objects)
    {
        for(T object: objects) 
        {
            object.clawBack();
        }           
    }
}

public class CommissionTrns implements Clawbackable {

    public void clawback(){
       // do clawback for commissions
    }
}

public class FinanceRequest implements Clawbackable {

    public void clawBack(){
      // do clwaback for FinanceRequest
    }

}

I prefer this approach, since I'm of the belief your domain should contain your logic; but I'm not fully aware of your exact wishes, so I'll leave it up to you.

With a double dispatch, you would pass the "ClawbackHandler" to the clawback method, and on the handler call the appropriate method depending on the type.

Solution 2

I think your best option is to simply name the method differently.

public void clawBackFinReqs(Collection<FinanceRequest> financeRequestList) {

}

public void clawBackComTrans(Collection<CommissionTrns> commissionTrnsList) {

}

In fact, it's not too bad, since you don't get anything extra out of having the same name on them.

Keep in mind, that the JVM will not decide which method to call at runtime. As opposed to virtual methods / method overriding resolution of overloaded methods are done at compile time. The Java Tutorials on method overloading even points out that "Overloaded methods should be used sparingly...".

Share:
12,318
n4rzul
Author by

n4rzul

Passionate about technology and loves to party. That's all for now. Boogity Boogity Amen.

Updated on June 05, 2022

Comments

  • n4rzul
    n4rzul almost 2 years

    I have FinanceRequests and CommisionTransactions in my domain. If I have a list of FinanceRequests each FinanceRequest could contain multiple CommisionTransactions that need to be clawed back. Dont worry how exactly that is done.

    The class below (very bottom) makes me feel all fuzzy and warm since its succint and reuses existing code nicely. One problem Type erasure.

    public void clawBack(Collection<FinanceRequest> financeRequestList)  
    public void clawBack(Collection<CommissionTrns> commissionTrnsList)
    

    They both have the same signature after erasure, ie:

    Collection<FinanceRequest> --> Collection<Object>  
    Collection<CommissionTrns> --> Collection<Object>  
    

    So eclipse complainst that:
    Method clawBack(Collection) has the same erasure clawBack(Collection) as another method in type CommissionFacade

    Any suggestions to restructure this so that it still an elegant solution that makes good code reuse?


    public class CommissionFacade
    {
        /********FINANCE REQUESTS****************/
        public void clawBack(FinanceRequest financeRequest)
        {
            Collection<CommissionTrns> commTrnsList = financeRequest.getCommissionTrnsList();           
            this.clawBack(commTrnsList);
        }
    
        public void clawBack(Collection<FinanceRequest> financeRequestList)
        {
            for(FinanceRequest finReq : financeRequestList) 
            {
                this.clawBack(finReq);
            }           
        }
    
        /********COMMISSION TRANSACTIOS****************/
        public void clawBack(CommissionTrns commissionTrns)
        {
            //Do clawback for single CommissionTrns         
        }
    
        public void clawBack(Collection<CommissionTrns> commissionTrnsList)
        {
            for(CommissionTrns commTrn : commissionTrnsList) 
            {
                this.clawBack(commTrn);
            }
        }
    
    }
    
  • n4rzul
    n4rzul over 12 years
    I like this approace too and agree that the logic should be in the domain. My example just feels to much like a helper or utils class that I would preferable avoid.
  • toto2
    toto2 over 12 years
    You give this solution as if it was some kind of compromise, but I think it is imperative that those methods be renamed. Actually the overloaded methods with the single argument must be renamed too. The code is very unclear now with those overloaded methods.
  • n4rzul
    n4rzul over 12 years
    Thanks Joeri, this is an elegant solution.
  • Werner Erasmus
    Werner Erasmus over 9 years
    This answer is not entirely satisfactory IMHO, especially the reference to Java Tutorials stating that Overloading makes code less readable is very subjective. The problem is that often implementation to interface is shareable. Take for example a simple interface like this: MyType provide(class<MyType> type) where type acts as discriminator. When not having the possibility to discriminate "generically" by type, we are forced to rename, but independent interfaces may use different names for the same purpose, which burdens the implementation unnecessarily.
  • Werner Erasmus
    Werner Erasmus over 9 years
    An example of this is using boost::mpl::identity<T> in c++ to discriminate based on type, simplifying choice of function names and allowing common implementation.