Friday, May 11, 2012

Accepting types from lowerbound(derived) to up(super) in Java generics

I wish Java had implemented generics first, so C# could copy this feature


import java.util.List;

import java.util.ArrayList;




public class Test {


    public static void main(String[] args) {

        // test addLot
        {
            List<Asset> assets = new ArrayList<Asset>();
            addLot(assets);

            List<Lot> lots = new ArrayList<Lot>();
            addLot(lots);

            List<CommercialLot> commercialLots = new ArrayList<CommercialLot>();
            // you cannot do this, compile-time error:
            // addLot(commercialLots);
        }

        // test addCommercialLot
        {
            List<Asset> assets = new ArrayList<Asset>();
            addCommercialLot(assets);

            List<Lot> lots = new ArrayList<Lot>();
            addCommercialLot(lots);

            List<CommercialLot> commercialLots = new ArrayList<CommercialLot>();
            addCommercialLot(commercialLots);
        }

    }

    public static void addLot(List<? super Lot> lots) {

        // you cannot do this, compile-time error:
        // lots.add(new Asset());

        // you can do this:
        lots.add(new Lot());

        // and so is this
        lots.add(new CommercialLot());

        ////////

        for(Asset a : (List<Asset>) lots) {
        }

        for(Lot l : (List<Lot>) lots) {
        }

        // you cannot do this, compile-time error:
        /*for(CommercialLot c : (List<CommercialLot>) lots) {
        } */
    }

    public static void addCommercialLot(List<? super CommercialLot> commercialLots) {

        // you cannot do this, compile-time error:
        // commercialLots.add(new Asset());

        // you cannot do this, compile-time error:
        // commercialLots.add(new Lot());

        // but of course, you can do this:
        commercialLots.add(new CommercialLot());

        ////////

        for(Asset a : (List<Asset>) commercialLots) {
        }

        for(Lot l : (List<Lot>) commercialLots) {
        }

        for(CommercialLot c : (List<CommercialLot>) commercialLots) {
        }
    }
}

class Asset {
}

class Lot extends Asset  {
}

class CommercialLot extends Lot {
}



Live test: http://ideone.com/dbgCU


The disadvantage of this approach though is it necessitates adding a new method with lowerbounded parameter whenever there's a new class that subclass the superclass. For alternative approach, read this: http://www.anicehumble.com/2012/05/c-said-java-said-oop-for-generics.html


No comments:

Post a Comment