2

We have a class structure like A<-B<-C<-D<-E<-F ( B extends A, C extends B and so on ).

I need to create a method acceptList(List<> list) in such a way that it can accept the List of Class A,C,E and do not accept List of B,D,F.

This question was asked to me in an interview.

giannis christofakis
  • 8,201
  • 4
  • 54
  • 65
Java_Jack
  • 577
  • 1
  • 5
  • 8

4 Answers4

2

Some trick like this might work, bear in mind that interfaces will always beat reflection ... thus if you can implement those type dependent functions in your interfaces directly then do it.

First your implementation of the classes:

public class A {

public boolean isAcceptable() {
    return true;
}

static class B extends A {

    @Override
    public boolean isAcceptable() {
        return !super.isAcceptable();
    }
}

static class C extends B {
    @Override
    public boolean isAcceptable() {
        return !super.isAcceptable();
    }
}

static class D extends C {
    @Override
    public boolean isAcceptable() {
        return !super.isAcceptable();
    }
}

static class E extends D {
    @Override
    public boolean isAcceptable() {
        return !super.isAcceptable();
    }
}

static class F extends E {
    @Override
    public boolean isAcceptable() {
        return !super.isAcceptable();
    }
}

}

then your acceptList(~):

public static boolean acceptList(List<? extends A> list){
    for (A a : list) {
        if(!a.isAcceptable()){
            return false;
        }
    }
    return true;
}
allprog
  • 16,540
  • 9
  • 56
  • 97
le-doude
  • 3,345
  • 2
  • 25
  • 55
  • This is not a type safe solution. Incompatibility will be revealed only at runtime. This may answer the question but is a practice that should be avoided whenever possible. – allprog Aug 28 '13 at 10:56
  • Absolutely right, but I believe the nature of is question is "at runtime", from the name of the function. Or else it is a bad case of the "bad-name-itis". – le-doude Aug 28 '13 at 10:59
  • @allprog could you explaing your "disclaimer"? – le-doude Aug 28 '13 at 11:09
  • Don't know whether it really answers the question, but I find the idea is just great! :) – proskor Aug 28 '13 at 11:18
  • @le_douard forget it, this is a great solution. It would be better if the value of acceptable did not rely so heavily on the actual hierarchy as it make the function really brittle. Suppose the next question was to implement the same functionality but all interfaces simply extended A. – allprog Aug 28 '13 at 12:06
1

Maybe the usage of condition - if and isInstance() ?

Pawel
  • 1,457
  • 1
  • 11
  • 22
0

Not possible, you can only specify allowed classes not classes that are not allowed.

Futhermore once a method is defined to accept a List<? extends A> it accepts List<A>, List<B>, List<C>,...

Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
GerritCap
  • 1,606
  • 10
  • 9
0

Generics do not allow differentiation. The type erasure will play its tricks.. I would suggest you to write a custom logic like the below:

public class Test {

public boolean accept(List<? extends A> list) {
    for (Object o : list) {
        if (o instanceof E && !(o instanceof F))
            return true;
        else if (o instanceof C && !(o instanceof D) && !(o instanceof F))
            return true;
        else if (o instanceof A && !(o instanceof B) && !(o instanceof D) && !(o instanceof F))
            return true;
        return false;
    }
    return false;

}

}

class A {

}

class B extends A {

}

class C extends B {

}

class D extends C {

}

class E extends D {

}

class F extends E {

}

Test Method to test the above code:

public static void main(String [] args){

    Test t = new Test();

    List<F> listF = new ArrayList<F>();
    listF.add(new F());
    System.out.println("List of F returns "+ t.accept(listF));

    List<E> listE = new ArrayList<E>();
    listE.add(new E());
    System.out.println("List of E returns "+ t.accept(listE));

    List<D> listD = new ArrayList<D>();
    listD.add(new D());
    System.out.println("List of D returns "+ t.accept(listD));

    List<C> listC = new ArrayList<C>();
    listC.add(new C());
    System.out.println("List of C returns "+ t.accept(listC));

    List<B> listB = new ArrayList<B>();
    listB.add(new B());
    System.out.println("List of B returns "+ t.accept(listB));

    List<A> listA = new ArrayList<A>();
    listA.add(new A());
    System.out.println("List of A returns "+ t.accept(listA));
}

Output of the test:

List of F returns false
List of E returns true
List of D returns false
List of C returns true
List of B returns false
List of A returns true

EDIT:

If you want to do some more research, this might help you . Get generic type of java.util.List

Community
  • 1
  • 1
dharam
  • 7,882
  • 15
  • 65
  • 93