Reputation: 27425
I have three classes (The number will be probably grow in the future):
public inteface Base{ }
public class Select implements Base{ }
public class Ast implements Base{ }
public class Gt implements Base{ }
I also need in a List
class
BaseList extends ArrayList<Base>{
public boolean add(Base b){
throw new UnsupportedOperationException("You should use add%ConcereteBaseType% method instead");
}
public boolean add(Select s){ }
public boolean add(Ast a){ }
public boolean add(Gt g){ }
}
The reason why I did this was the fact that I don't want anyone to adds elements via a pointer to Base
. In my concrete situation this would be unsafe.
But the disadvantage is that it will be discovered only at runtime.
I also need to iterate over the list.
Is it a good practice to do such things?
Upvotes: 11
Views: 1535
Reputation: 421130
Using an interface
is fine. (Turning Base
into an abstract class won't buy you anything here.)
You should favor composition over inheritance here though, and implement Iterable<Base>
to be able to use it in enhanced for loops etc.
class BaseList implements Iterable<Base> {
private List<Base> list = new ArrayList<>();
public boolean add(Select s) {
return list.add(s);
}
public boolean add(Ast a) {
return list.add(a);
}
public boolean add(Gt gt) {
return list.add(gt);
}
@Override
public Iterator<Base> iterator() {
return Collections.unmodifiableList(list).iterator();
}
}
You can then iterate over the list as follows:
for (Base b : yourBaseList) {
...
}
Upvotes: 12
Reputation: 86855
You could make Base
an abstract
class, as these could never be instantiated, your list would be safe.
My the way: I really don't understand why you would like to throw an exception for add(Base b)
when base is an interface
which itself can never be an object.
Otherwise, use delegate/wrapper pattern, means: Do not extend ArrayList
, but create a class holding an ArrayList.
class BaseList {
private List<Base> list = new ArrayList<>();
public boolean add(Select s) {
return list.add(s);
}
//etc
}
Upvotes: 7