Category Archives: pattern

Studying Builder Pattern with Inheritance

Just to pay some tech debts.

Builder Pattern alone is easy to understand, but not so much if inheritance is concerned.

(Part I) understand the problem

First, we need to understand how inner class works.

Given A <— B (B is subclass of A), and A.Builder is inner class of A, and B.Builder is inner class of B. If we have A.Builder <— B.Builder as well, what is the consequence of following calls?

  1. new B.Builder(): A and B are not created, but A.Builder() is called and then B.Builder() is called. new B.Builder().getClass()returns B$Builder;
  2. new B.Builder().Bmethod(): call B’s Bmethod (who returns B$Builder); getClass() returns B$Builder;
  3. new B.Builder().Bmethod().Amethod(): call A’s Amethod (who returns A$Builder); but getClass() still returns B$Builder();
  4. new B.Builder().Bmethod().Amethod().build(): call B’s build() (who returns new B(B$Builder)) because Amethod return “this”, by no means compiler knows who is “this”; Once B(B$Builder) is called, first B’s super(B$Builder) is called, and then B’s rest is called. So finally, B is created and returned. However, this only happens in runtime. In compile time, the build() that is involved is A’s build() . So casting has to happen so that compiler can pass.

Compile time follows the definition/ signature strictly, but in runtime, jvm finds the nearest method to call. Method getclass() only returns the runtime class, and down cast (from parent to child) is only possible if in runtime parent type is actually a child object. Compiler does not know what is “this” it is referring, so runtime cast must be done.

Therefore, as Eamonn McManus mentioned in the post,

new B.Builder().Bmethod().Amethod().build() will be compiled, but the sequence requirement is not a pleasant requirement, and a down cast must be there in order to do sth. like

B b = (B) new B.Builder().Bmethod().Amethod().build();

(Part II) explore to solve the problem

In summary, the problem happens because in parent class A$Builder we have a method Amethod who returns this, but in compile time, compiler correctly thinks “this” is A$Builder, but what we hope is that “this” is B$Builder. So we need a trick to cheat compiler, here we go,
Continue reading