As @chrylis noted in the comments, you can genericize BaseClass
:
public abstract class BaseClass<T extends BaseClass> {
private Alpha a;
private Beta b;
public Alpha getAlpha() {
return a;
}
public Beta getBeta() {
return b;
}
@SuppressWarnings("unchecked")
public T setAlpha(Alpha a) {
this.a = a;
return (T) this;
}
@SuppressWarnings("unchecked")
public T setBeta(Beta b) {
this.b = b;
return (T) this;
}
}
and extend as follows:
Foo:
public class Foo extends BaseClass<Foo> {
private Gamma g;
@Override
public Foo setBeta(Beta b) {
super.setBeta(b);
doSomethingElse();
return this;
}
private void doSomethingElse() { }
public Gamma getGamma() {
return g;
}
public Foo setGamma(Gamma g) {
this.g = g;
return this;
}
}
Bar:
public class Bar extends BaseClass<Bar> {
private Omega o;
@Override
public Bar setAlpha(Alpha a) {
super.setAlpha(a);
doSomethingElse();
return this;
}
private void doSomethingElse() { }
public Omega getOmega() {
return o;
}
public Bar setOmega(Omega o) {
this.o = o;
return this;
}
}
This introduces a couple unchecked cast warnings, which I suppressed. It compiles, but I haven't tried actually doing anything with it.