Re: Realtime class update
On Jul 27, 7:41 am, O.L. <n...@undefined.invalid> wrote:
I suppose this will cause problems with 'instanceof' and old/new
instances, but I think this is the best (and only) solution.
Use instanceof on a common supertype, e.g. have WhateverBase and make
WhateverDerived1, WhateverDerived2, etc. be your versions. If they
adhere to a common contract checking for being "instanceof
WhateverBase" should suffice where you are forced somehow to use
instanceof and not polymorphism.
Maybe equals()? Define that in WhateverBase in terms of contract
methods if possible. If you must do special stuff depending on exact
implementation, make WhateverBase have a getVersion method and write:
(in WhateverBase)
public final boolean equals (Object o) {
if (this == o) return true;
if (o == null || !(o instanceof WhateverBase)) return false;
WhateverBase wb = (WhateverBase)o;
if (wb.getVersion() > getVersion()) return wb.equalsImpl(this);
return equalsImpl(wb);
}
protected abstract int getVersion ();
protected abstract boolean equalsImpl (WhateverBase wb);
(in WhateverDerived1)
protected int getVersion () { return 1; }
protected boolean equalsImpl (WhateverBase wb) {
WhateverDerived1 wd = (WhateverDerived1)wb;
// Whatever to compare two WhateverDerived1s
return something;
}
(in WhateverDerived2)
protected int getVersion () { return 2; }
protected boolean equalsImpl (WhateverBase wb) {
if (wb instanceof WhateverDerived1) return
equalsImpl2((WhateverDerived1)wb);
WhateverDerived2 wd = (WhateverDerived2)wb;
// Whatever to compare two WhateverDerived2s
return something;
}
private boolean equalsImpl2 (WhateverDerived1 wd) {
// Whatever to compare a WD2 and a WD1
return something;
}
I trust you see the pattern here. The key thing is to assign version
numbers sequentially. Each class needs to know how to compare itself
to each previous version, and needs its equalsImpl to be the one that
gets called. If you do otherwise the code will break -- it will
sometimes call an old version equalsImpl with a newer version
parameter and consequently throw a ClassCastException on the last cast
in the called equalsImpl method.
This is assuming all the WDs extend WB directly, never each other,
which I'll also recommend to ensure the CCE is thrown instead of
subtler broken behavior occurring instead, such as simply wrong return
values from some calls to equals().
This can be generalized to anything else that needs to effectively
dispatch on two run-time types and not just one. It won't be nearly as
easy or tidy however if you end up with two different serially-
versioned types and a binary operation between them...