#

Tuesday, January 11, 2011

Setter Chaining & generics

Although the concept of setter chaining is not new, thanks to a few good men I've picked the habit. However when using Inheritance, the setter of the base class returns type of "base class". This can disrupt the "coolness" of using chaining.

For the rest I'll let the code talk about the issue & a possible solution in more detail:


package com.arjun.misc;

/**
* "Setter chaining". The issue is that it returns the object of the
* type of the class in which the setter is.
* For Inheritance concepts this means if A<--B; then B.a()
* will return A not B (exclude overriding).
* This hardly helps chaining. Using generics to solve the problem
*
* @author Arjun Dhar | www.neurosys.biz
* */

public class GenericChainingSetters {
private static class A<T extends A> {
T setA(String something) {
return (T)this;
}
}

private static class B<T extends B> extends A<T> {
T setB(String something) {
return (T)this;
}
}

private static class C<T extends C> extends B<T> {
T setC(String something) {
return (T)this;
}
}

public static void main(String[] args) {
//WORKS
B<B> b = new B();
b.setA("abc").setB("abc again?!");

//WORKS
C<C> c = new C();
c.setA("abc").setB("abc again?!").setC("Hurray!");
}
}

Only thing is that as with Generics (erasure),
one cant (can but should not logically) do something stupid like:
B<C> b = new B();


Thoughts & suggestions welcome

thanks
-Arjun

Click here to see better way using Java 8

2 comments:

  1. Good stuff, but I think

    c.setA("abc").setB("abc again?!").setC("Hurray!")

    should not work. Reasoning this out:

    typeOf(c) = C
    typeOf(c.setA("abc")) = C
    typeOf(c.setA("abc").setB("abc again?!")) = B

    B doesn't have a setC method

    ReplyDelete
  2. I wont disagree with that, because the definition of typeOf() is not clear to me. I think its a C operator that may or may not be mathematically correct.

    Still, lets assume your typeOf(..) analogy is correct.

    In my opinion it is also important to question; if the idea of chaining also implies:
    Mathematical Commutativity (i.e. A x B x C = C x B x A) => setA().setB().setC() = setA().setC().setB() = setC().setB().setA()

    If one denies this for Inheritance, then one must deny this also for the same object (without inheritance).

    So I leave this to you.
    If you feel that "Commutativity" holds for the same object
    => Then that mathematically & Logically implies, it should hold for inheritance
    => Then that mathematically & Logically implies, that it contradicts the typeOf(...) analogy.

    However, if you feel Commutativity should not hold. Then both the school of thought converge to a single answer.

    imo Commutativity "should hold" but I cant be too sure. Need to think on this more.
    Very interesting.

    Each setter changes the state of an object. So should the result of the chain be the same irrespective of the order?

    ReplyDelete