I have an interface, Attribute
, that is going to be implemented in various ways,
class AttributeA implements Attribute{\\..}
class AttributeB implements Attribute{\\..}
Then I'm planning to have a class containing a list of interface members
class Example {
List<Attribute> attributes;
//..
}
And then I'm planning to have a class containing a list of those
class ExamplesAndMore {
List<Example> examples;
//..
}
But, I want any instatiation of ExamplesAndMore
to make sure that it only takes examples of the same type or signature. That is, I want to make sure the examples
list doesn' t contain one member whose attributes
list is of the form <AttributeA, AttributeA, AttributeB>
while another is of the <AttributeA, AttributeA, AttributeA>
or <AttributeA, AttributeA, AttributeB, AttributeB>
.
I could just check everywhere I modify the examples
list.
A comment asked me to be more specific, so I'll give code for how I could do this.
class Example {
List<Attribute> attributes;
public List<Class<? extends Attribute>> getSignature(){
List<Class<? extends Attribute>> result = new ArrayList<Class<? extends Attribute>>();
for(Attribute attribute : attributes){
result.add(attribute.getClass());
}
return result;
}
//..
}
public class ExamplesAndMore {
List<Example> examples;
List<Class<? extends Attribute>> signature;
public ExamplesAndMore(List<Class<? extends Attribute>> signature){
this.signature = signature;
this.examples = new ArrayList<Example>();
}
public void addExample(Example example){
if(!example.getSignature().equals(signature)){
throw new IllegalArgumentException(String.format("This takes examples with signature %s", signature.toString()));
}
examples.add(example);
}
//..
}
But I wonder if this is a good way of going about this, checking for types at runtime doesn't feel nice. Basically I think this code smells a bit. One way this smell might manifest as an actual problem is when I create
class GenericAttribute<T> implements Attribute{\\..}
with the intention of not having an example with an attribute of type GenericAttribute<ClassA>
and one of type GenericAttribute<ClassB>
in the same list. Then type erasure ruins my day.
Also, when I don't need examples to contain arbitrarily many attributes but only a fixed number (say 3), then my problem goes away entirely and I can even check at compile-time by having
class Example<T1, T2, T3> {
//..
}
public class ExamplesAndMore<T1,T2,T3> {
List<Example<T1,T2,T3> examples;
public void addExample(Example<T1,T2,T3> example){\\..}
//..
}
However this approach obviously doesn't extend to examples with arbitrarily many attributes.
Anyway, I feel that I'm missing some obvious technique or something. Is there a nice pattern that deals with this, am I designing this badly? Chances are I'm not the first one doing this.
Also sorry for the lousy title, If I had a better description for my problem I'd probably have better luck searching for an answer and wouldn't have to ask...