I was wondering how to design a system in which I have a class Super and a couple of classes that are subclasses of Super (let's say Sub1, Sub2, Sub3) and I want a class Cool. Now there are two things I want to have:
Any suggestions? Hints?
I was wondering how to design a system in which I have a class Super and a couple of classes that are subclasses of Super (let's say Sub1, Sub2, Sub3) and I want a class Cool. Now there are two things I want to have:
Any suggestions? Hints?
Maybe something like this:
class Super {}
interface Cool { boolean isCool(); }
class IsCool implements Cool {
public boolean isCool() { return true; }
}
class NotCool impolements Cool {
public boolean isCool() { return false; }
}
interface CoolSupporter {
boolean isCool();
Cool getCool();
}
class Sub1 extends Super implements CoolSupporter {
private Cool cool;
public Sub1() { this(new NotCool()); }
public Sub1(Cool cool) { this.cool = cool; }
public boolean isCool() { this.cool.isCool(); }
public Cool getCool() { return this.cool; }
}
class Sub2 extends Super implements CoolSupporter {
private Cool cool;
public Sub1() { this(new NotCool()); }
public Sub1(Cool cool) { this.cool = cool; }
public boolean isCool() { this.cool.isCool(); }
public Cool getCool() { return this.cool; }
}
class Sub3 extends Super {}
class CoolList {
private List<CoolSupporter> list = new ArrayList<CoolSupporter>();
public void add(CoolSupporter coolSupporter) {
if (coolSupporter.isCool()) {
list.add(coolSupporter);
} else {
throw new UncoolException();
}
}
}
Arne's answer kind of does what you want, but I find it overly complicated. Maybe I'm missing something? Why not just:
class Super { }
interface Cool { boolean isCool(); }
class CoolImpl extends Super implements Cool {
private boolean cool;
public CoolImpl(boolean cool) { this.cool = cool; }
public boolean isCool() { return this.cool; }
}
class Sub1 extends CoolImpl { }
class Sub2 extends CoolImpl { }
class Sub3 extends Super { }
class CoolList extends ArrayList<Cool> {
public boolean add(Cool cool) {
if (!cool.isCool()) {
return false;
}
return super.add(cool);
}
}
You can create an marker interface say cool. Let class Sub1 and Sub2 implements this interface and before adding to the list check for instance of cool
may be this can help.
You can't have a class optionally belonging to a type in Java. Though you may subclass Sub1, with one subclass implementing an interface Cool and the other not:
class Super { }
interface Cool { }
class Sub1 extends Super { }
class Sub1Cool extends Sub1 implements Cool { }
class Sub2 extends Super { }
class Sub2Cool extends Sub2 implements Cool { }
class Sub3 extends Super { }
class CoolList extends ArrayList<Super> {
public boolean add(Super sup) {
if (!(sup instanceof Cool)) {
return false;
}
return super.add(cool);
}
}
You might also discard the Cool concept and use a visitor pattern:
class Super {
public boolean addTo(List<Super> coolList) {
if (canBeAddedToCoolList()) {
return coolList.add(this);
}
return false;
}
protected boolean canBeAddedToCoolList() {
return false;
}
}
class Sub1 extends Super {
protected boolean canBeAddedToCoolList() {
// check logic to allow/disallow addition
}
}
IMO, you need to have a overrided List (Say MyList, that overrides add()).
In add(), Check if the object you are adding is Cool, if it is so, then add it part of the list. If not then just gracefully disregard it.
Does this help?
The simplest way you can manage this is to further subclass Sub1 (CoolSub1 and NotCoolSub1) and Sub2 (CoolSub2 and NotCoolSub2).
CoolSub1 and CoolSub2 can then implement Cool ( Cool should be an interface and not a class)
You can then define
List<Cool>
which will accept implementations of Sub1 and Sub2, but only if they implement Cool.