I have a problem with generic class hierarchy and method override. I tried to do something like below:
public class Configuration<S> { private List<S> elements; <T extends Configuration<S>> Configuration<S> merge(T anotherConfig) { return anotherConfig; } }
and the subclass looks like:
public class ExtendedConfiguration extends Configuration<String> { @Override ExtendedConfiguration merge(ExtendedConfiguration anotherConfig) { return anotherConfig; } }
However, subclass does not compile and I have no clue how to declare method in Configuration class so I can override it in subclass with subclass type as parameter. I want to avoid explicit casting.
Advertisement
Answer
Due to Erasure: merge
in Configuration
becomes:
Configuration merge(Configuration anotherConfig) { return anotherConfig; }
For ExtendedConfiguration
to override merge
, it must have Configuration
as method param type. So, below ExtendedConfiguration
is fine:
class ExtendedConfiguration extends Configuration<String> { @Override Configuration<String> merge(Configuration anotherConfig) { return anotherConfig; } }
@Override
instructs the compiler to check if the method is being inherited.
With the declaration in question:
public class ExtendedConfiguration extends Configuration<String> { @Override ExtendedConfiguration merge(ExtendedConfiguration anotherConfig) { return anotherConfig; } }
it’s overloading instead. If you remove @Override
, it will compile fine.
To achieve your requirement, you can use recursive generics:
The updated declarations may look like:
Configuration
class Configuration<T extends Configuration<T, S>, S> { private List<S> elements; Configuration<T, S> merge(T anotherConfig) { return anotherConfig; } }
ExtendedConfiguration
class ExtendedConfiguration extends Configuration<ExtendedConfiguration, String> { @Override ExtendedConfiguration merge(ExtendedConfiguration anotherConfig) { return anotherConfig; } }