I'm having hard time with creating a type safe behavior, I'll use a general example in order to emphasize my issue:
I have an interface BoxCreator
which is defined by:
public interface BoxCreator{
public Box create(int id ,List<Box> others);
}
and a general Box
class (A Box
can contain several other Box
es) which has methods like int getId()
, Box getInternalBox(int id)
.
Suppose I have a class Shed implements BoxCreator,Container
(where container is just a general interface with action like add and remove ). I can put new things inside the shed and it'll box them in a ShedBox
which implements Box
.
So far so good, the problem arises when I try to make some other class that will do things a little differently, for example CoolShed extends Shed implements BoxCreator
which will put thing into CoolBox
es (which extend ShedBox
).
For now it works but I have several down-casts in the CoolShed
class (from a general Box
to CoolBox
) that might be 'not pretty'.
What I'm looking for is a way to make
Shed<T extends ShedBox> implements BoxCreator<T>
And then when implemeting the CoolShed
I'd just do something like
CoolShed extends Shed<CoolBox> implemets BoxCreator<CoolBox>
I was trying to make the various classes generic but but couldn't create a generic create
method because I can't instantiate a T
or return one for that matter. So I'm a little lost.
Several notes:
CoolShed
uses a lot of the Shed
logic but I'd just to make it use the CoolBox
class as a container. Shed
has an instance of a BoxCreator
so when creating CoolShed
I just make CoolShed
the new creator and it works. CoolShed
will only have CoolBox
instances but I wouldn't really mind anything extending ShedBox
in the Shed
class. I just couldn't find a good explanation of how to achieve the desired behavior nor I could tell whether my existing casts are OK
I know my example is quite long I'd be happy to make it clearer in any way I can.
EDIT
A code template to make the question clearer:
public interface BoxCreator{
public Box create(int id ,List<Box> others);
}
public interface Box{
void put()
void addAnother(Box box);
}
public class ShedBox implements Box{
void put()
void addAnother(Box box);
}
public class CoolBox extends ShedBox{ //has some extra features but moslty the same
void put()
void addAnother(Box box);
}
public interface Container {
Box addValue(int value);
Box getBox(int id);
.
.
}
public class Shed implements Container, BoxCreator {
BoxCreator creator;
SomeCollection<Box> boxes;
Shed(){
creator = this;
.
.
.
}
Box addValue(int id){
.
.//some logic to get otherBox here
.
Box box = creator.createBox(id,otherBox);
}
Box getBox(int id);
public Box create(int id ,Box other){
return new ShedBox(id,others)
}
}
public class CoolShed extends Shed implements BoxCreator {
CoolShed(){
creator = this;
.
.
.
}
addValue(int id){
Box boxAdded = super.add(id)
.
.
.
CoolBox box = (CoolBox)boxAdded; // The questionable cast
.
. //Some logic that involves CoolBox specific actions
.
}
public Box create(int id ,Box other){
return new CoolBox(id,others)
}
}
(Previous answer removed)
EDIT: This solution should be better, assuming others
may contain any box:
public interface BoxCreator {
public Box create(int id, List<Box> others);
}
public class Shed implements BoxCreator {
@Override
public ShedBox create(int id, List<Box> others) {
...
}
}
public class CoolShed extends Shed {
@Override
public CoolBox create(int id, List<Box> others) {
...
}
}
Also, don't do this:
BoxCreator creator;
creator = this;
creator.create(...);
Instead, you should either write this.create(...)
or simply create(...)
. Then you won't have to cast from Box
to the desired subclass, since the value returned from create
will already be of type ShedBox
or CoolBox
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.