Reputation: 2912
I have a beginners question concerning Java.
I have a class Thing<T>
that has an attribute "attribute".
I want the attribute to be either a LinkedList<T>
(as given by Java) or a self-defined type named My_Type<T>
, depending on the boolean that is given to the constructor of Thing
. Like this:
public class Thing<T> {
private ??? attribute; // Type is not given yet. How do I do this?
public Thing(boolean which) {
if (which)
attribute = new LinkedList<T>();
else
attribute = new My_Type<T>();
}
...
}
Thing
has some more methods that use add
and remove
, which are both implemented for LinkedList
and My_Type
.
How do I declare my attribute? Declaring it as Object is no option because Object does not know the methods add
and remove
. I thought about using interfaces, but I don't know how.
If both LinkedList
and My_Type
were written by me, I could let them both implement the interface LinkedListOrMy_Type<T>
which has add
and remove
as methods. Then, instead of
private ??? attribute;
I would write
private LinkedListOrMy_Type<T> attribute;
And everything would be okay. But because I cannot modify the code of LinkedList
, I don't know how to work around this. Any suggestions?
Making My_Type
implement the List
interface (given by Java) is not an option either, because there are so many methods that I would need to implement into My_Type
. But I only want add
and remove
. I know it's a possible workaround - I could let My_Type
throw an UnsupportedOperationException
in every method of List except add
and remove
. But I believe I could learn more about good programming if you give me a suggestions that is not as dirty as this!
Upvotes: 0
Views: 169
Reputation: 59146
You can't have one field that can be of two different types in Java; the closest you can do is have a field that is some common base type. So you have a few options.
Use a common base type that provides add
and remove
. The obvious candidate for this is Collection
, which is implemented by LinkedList
.
Use a common base type that does not provide the methods you want, but cast the object when you need to. In this case you could simply have a field of type Object
, and each time you want to make use of your field, you have to cast it to either of the actual types.
Use two fields. This would seem to make more sense - having one variable of two different types is not really how variables work.
Wrap LinkedList
and MyType
in classes that have a common base type that provides the methods you need.
For instance:
interface WrapperThing<T> {
void add(T item);
void remove(T item);
}
class ListWrapperThing<T> implements WrapperThing<T> {
private List<T> list;
public ListWrapperThing() {
list = new LinkedList<T>();
}
public void add(T item) {
list.add(item);
}
public void remove(T item) {
list.remove(item);
}
}
class MyTypeWrapperThing<T> implements WrapperThing<T> {
private MyType<T> my;
public ListWrapperThing() {
my = new MyType<T>();
}
public void add(T item) {
my.add(item);
}
public void remove(T item) {
my.remove(item);
}
}
Then you can use a WrapperThing<T>
variable much as if it were a variable that could (inside it) contain either a List
or a MyType
object.
Upvotes: 1
Reputation: 3201
Going the interface route seems a good idea. Define your own interface MyInterface
and let MyType
implement it:
class MyType implements MyInterface
Now here's the trick: LinkedList
isn't final! Use OOP to your advantage by extending the JDK class and letting it implement your interface:
class MyLinkedList extends LinkedList implements MyInterface
Let us know if this will do the trick for you...
Upvotes: 1
Reputation: 5195
Well, you could implement the interface List
in your type. It is implemented by all list like classes in Java. Of course it offers more methods than you probably need, but you could implement only those you need and throw for example an not implemented exception in others.
Upvotes: 0