\$\begingroup\$
\$\endgroup\$
0
I'm implementing Curiously Recurring Template Pattern(CRTP) in Java as follows.
The Interface:
/**
* Reason for the generic Value<T extends Value>
* Value<IntValue> x; // legal, IntValue implements Value interface so allowed
* Value<Integer> x; // illegal, does not implement Value interface
*/
@SuppressWarnings("rawtypes")
public interface Value<T extends Value> {
T deepCopy();
}
Classes implementing it:
public class IntValue implements Value<IntValue> {
Integer value;
public IntValue(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
@Override
public IntValue deepCopy() {
return new IntValue(value);
}
}
/**
* // Valid
* List<IntValue> ints = Arrays.asList(new IntValue(Integer.valueOf(5)));
* ArrayValue<IntValue> arr = new ArrayValue<>(ints);
*
* // Invalid
* List<Integer> ints = Arrays.asList(Integer.valueOf(5));
* ArrayValue<Integer> arr = new ArrayValue<>(ints);
*/
@SuppressWarnings("rawtypes")
public class ArrayValue<T extends Value> implements Value<ArrayValue<T>> {
List<T> values;
public ArrayValue() {
this(new ArrayList<>());
}
public ArrayValue(List<T> values) {
this.values = values;
}
@SuppressWarnings("unchecked")
@Override
public ArrayValue<T> deepCopy() {
List<? super Value> copyValues = new ArrayList<>();
values.forEach(value -> copyValues.add(value.deepCopy()));
return new ArrayValue<T>((List<T>) copyValues);
}
}
//Static Function using the interface
@SuppressWarnings("rawtypes")
public static Value sub(Value a, Value b)
{
if(a instanceof IntValue && b instanceof IntValue)
{
return new IntValue( ((IntValue)a).getValue() - ((IntValue)b).getValue());
}
else
{
throw new TypeMismatchException("Operation not supported");
}
return NullValue.NULL_VALUE;
}
However I have to suppress warnings multiple times throughout the implementation.
Are the uses of suppress annotation justified?
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
1 Answer 1
\$\begingroup\$
\$\endgroup\$
As far I can tell this doesn't generate any warnings:
class IntValue implements Value<IntValue> {
Integer value;
public IntValue(Integer value) {
this.value = value;
}
public Integer getValue() {
return value;
}
@Override
public IntValue deepCopy() {
return new IntValue(value);
}
}
class ArrayValue<T extends Value<T>> implements Value<ArrayValue<T>> {
List<T> values;
public ArrayValue() {
this(new ArrayList<>());
}
public ArrayValue(List<T> values) {
this.values = values;
}
@Override
public ArrayValue<T> deepCopy() {
List<T> copyValues = new ArrayList<>();
values.forEach(value -> copyValues.add(value.deepCopy()));
return new ArrayValue<>(copyValues);
}
}
But it makes more sense to do it without CRTP:
public interface Value<T> {
Value<T> deepCopy();
T getValue();
}
class IntValue implements Value<Integer> {
Integer value;
public IntValue(Integer value) {
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
@Override
public IntValue deepCopy() {
return new IntValue(value);
}
}
class ArrayValue<T> implements Value<List<Value<T>>> {
List<Value<T>> values;
public ArrayValue() {
this(new ArrayList<>());
}
public ArrayValue(List<Value<T>> values) {
this.values = values;
}
@Override
public ArrayValue<T> deepCopy() {
List<Value<T>> copyValues = new ArrayList<>();
values.forEach(value -> copyValues.add(value.deepCopy()));
return new ArrayValue<>(copyValues);
}
@Override
public List<Value<T>> getValue() {
return values;
}
}
class X {
public static Value sub(Value<Integer> a, Value<Integer> b) {
return new IntValue(b.getValue() - b.getValue());
}
}
answered Sep 14, 2018 at 10:57
lang-java