Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
405 views
in Technique[技术] by (71.8m points)

java - How to use method with generics and inheritance?

Having the following classes:

public interface Step<C extends Config> {
  void setConfig(C config);
}

and

public class ValidationStep implements Step<ValidationConf> {
  public void setConfig(ValidationConf conf) {}
  // implementation
}

and

public class ProcessStep implements Step<ProcessConf> {
  public void setConfig(ProcessConf conf) {}
  // implementation
}

and

public interface Config {
  Class<? extends Step> type();
}

and

public class ValidationConf implements Config {
  public Class<? extends Step> type() {
    return ValidationStep.class;
  }
}

and

public class ProcessConf implements Config {
  public Class<? extends Step> type() {
    return ProcessStep.class;
  }
}

so, the application needs to dynamically instantiate Step subclasses objects, set the configuration accordingly and run the step, like this.

List<Config> configs = loadConfigsFromRepository(); // contain all subtypes of Config
for (Config conf: configs) {
  Step<? extends Config> step = conf.type().getDeclaredConstructor().newInstance();

  step.setConfig(conf); // compiler complains

}

Error message:

"The method setConfig(capture#8-of ? extends Config) in the type Step<capture#8-of ? extends Config> is not applicable for the arguments (Config)".

Checking the documentation, looks like Java won′t be friendly in this case: https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html

What are the possible solutions to overcome this code restriction step.setConfig(conf);?

EDITED [SOLUTION]

Code can be viewed here: https://github.com/danieldestro/cucumber-salad/tree/generics/src/main/java/my/generics

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Because Step.setConfig( Config ) is a ?consumer“, one way to resolve the ?is not applicable for the arguments (Config)“ error you get is to use a lower bound like I demonstrate here

…  
List< ? extends Config > configs = loadConfigsFromRepository( ); // contain all subtypes of Config
  
for ( Config conf: configs ) {
    Step< ? super Config > step = conf.type( ).getDeclaredConstructor( ).newInstance( );

      step.setConfig( conf ); // *set* makes Step a ?consumer“
}
…

That way you don't need the cast that the other answer proposes.

My loadConfigsFromRepository( ) is implemented like

static List< ? extends Config > loadConfigsFromRepository(){ 
    
    return of( new ValidationConf( ), new ProcessConf( ) );        
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...