简体   繁体   中英

How can I add consumers of different arguments to a list?

I want to collect a list of Processors who can operate on different parameters.

Here are some example classes

public abstract class AbstractHistory { 
    public String getTlp() { return "";  }          
    }

public class SynchResourcConfig {
   public boolean isEnabled() { return true); }
  }

public class SynchClassTlpFilterConfig extends SynchResourcConfig {
    public String getClass() { return ""; } 
  }

This is the interface I want each element of the list to implement

public interface ConfigProcessingFilter {
    public boolean shouldProcess(AbstractHistory history, SynchResourceConfig config);
}

This class ideally would hold all the processors in a list

The idea being, when 'shouldProcess()' gets invoked, it can reply with the result of any included processor.

public class ConfigProcessor {

    protected List<ConfigProcessingFilter> filters = new ArrayList<>();

    public boolean shouldProcess(AbstractHistory history, SynchResourceConfig config) {
        return config.isEnabled() && filters.stream().anyMatch(
            (filter) -> filter.shouldProcess(history, config));
    }

    public ConfigProcessor addFilter(ConfigProcessingFilter filter) {
        filters.add(filter);
        return this;
    }
}

The dilemma

I want to allow for processing on subclasses of the data in the list as well. But I'm getting the error indicated in the constructor's comments.

public class ClassTlpProcessingFilter extends ConfigProcessor {

    public ClassTlpProcessingFilter() {
        /*
        Compiler underlines: `processByClassTlp()` with error:
        The method processByClassTlp(AbstractHistory, SynchClassTlpFilterConfig) 
        in the type ClassTlpProcessingFilter is not applicable 
        for the arguments (AbstractHistory, SynchResourceConfig)
        */
        addFilter((history, config) -> processByClassTlp(history, config));
    }

    public boolean processByClassTlp(AbstractHistory history, SynchClassTlpFilterConfig config) {
        return config.getClass().equals(history.getTlp());

    }

}

Looking at the issue

The List contains ConfigProcessingFilter . Each of those items has a shouldProcess() method.

I was hoping this would allow any subclass of the described types to be accepted as parameters.But obviously that isn't working.

Is there anything that could be done to fix this?

Thanks in advance

I think I figured out how to do it. It seems to work if I propagate the elements' type all the way up from the lowest child class up to the parent class.

Interface updated with type params

public interface ConfigProcessingFilter<H extends AbstractHistory, C extends SynchResourceConfig> {
    public boolean shouldProcess(H history, C config);
}

Processor updated to operate on generic types

public class ConfigProcessor<H extends AbstractHistory, C extends SynchResourceConfig> implements ConfigProcessingFilter<H, C> {

    private List<ConfigProcessingFilter<H, C>> filters = new ArrayList<>();

    public boolean shouldProcess(H history, C config) {
        return config.isEnabled() && filters.stream().anyMatch(
                (filter) -> filter.shouldProcess(history, config));
        }
    }

    public ConfigProcessor addFilter(ConfigProcessingFilter<H, C> filter) {
        filters.add(filter);
        return this;
    }
}

Update to the subclass

public class ClassTlpProcessingFilter<H extends AbstractHistory, C extends SynchClassTlpFilterConfig> extends ConfigProcessor<H, C> {

    public ClassTlpProcessingFilter() {
        addFilter((history, config) -> processByClassTlp(history, config));
    }

    public boolean processByClassTlp(AbstractHistory history, SynchClassTlpFilterConfig config) {
        return config.getClass().equals(history.getTlp());

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM