In my implementation I want to have different return type of the method

Tags:



I have the following problem. I have the interface:

public interface Parser {
    public Map<String, List<String>> parse() throws IOException;
}

I have two implementations:

public class RacerInfoParser implements Parser{

    private final Path path;

public RacerInfoParser(Path path) {
    this.path = path;   
}

@Override
public Map <String, List<String>> parse() throws IOException {
    try (Stream<String>lines = Files.lines(path)){
        
        Map <Object, Object> map = lines.collect(Collectors.toMap(
                string -> string.substring(0,3),
                string -> Arrays.asList(string.substring(4).split("_"))));
        
        Map<String, List<String>> result = new HashMap<>((Map) map);
        return result;
        }
    }
}

and

public class TimeParser implements Parser {

    private final Path path;

public TimeParser(Path path) {
    this.path = path;   
}


@Override
public Map <String, List<String>> parse() throws IOException {
    try (Stream<String>lines = Files.lines(path)){
        
        Map <Object, Object> map = lines.collect(Collectors.toMap(
                string -> string.substring(0,3),
                string -> Arrays.asList(string.substring(3).split("_"))));
        Map<String, List<String>> result = new HashMap<>((Map) map);
    return result;
        }
    }
}

What I want to do is to change the code and the return type of TimeParser so that it returns the result of type Map<String, List <LocalTime>. I have read that in order to have a different type I need to have a sub-class of the parent type, but I don’t understand how to do it in my case.

P.S. I know that Map<String, List<String>> result = new HashMap<>((Map) map); is a bad code, but I don’t know yet how to properly convert Map<Object, Object to Map<String, List<String>>. If you have any suggestions I will be glad to listen to them:).

P.S.S. I use these two implementations because I beleive they do the same thing: parse text from log and txt files:

    public class RacerBuilder {
        public List<Racer> buildRacers () throws URISyntaxException, IOException {
    
            Parser racerInfoParser = new RacerInfoParser(Paths.get(getClass().getClassLoader()
                      .getResource("abbreviations.txt").toURI()));
            Parser startTimeParser = new TimeParser(Paths.get(getClass().getClassLoader()
                      .getResource("start.log").toURI()));
            Parser endTimeParser = new TimeParser(Paths.get(getClass().getClassLoader()
                      .getResource("end.log").toURI()));
            
            Map<String, List<String>> racerInfoMap = racerInfoParser.parse();
            Map<String, List<String>> startTimeMap = startTimeParser.parse();
            Map<String, List<String>> endTimeMap = endTimeParser.parse();
    
            return racerInfoMap.keySet().stream()
                    .map(i -> new Racer (i,
                            racerInfoMap.get(i).get(0),
                            racerInfoMap.get(i).get(1),
                            startTimeMap.get(i).get(1),
                            endTimeMap.get(i).get(1),
                            endTimeMap.get(i).get(0)))
                    .collect(Collectors.toList());  
           }
}

Racer class now has several fields, all of them are Strings. I want it to have 2 fields of type LocalTime.

Answer

I’d wrap the Map<String, List<String>> in a new class with a getter, let’s call it MapAsString. Make it part of a class hierarchy so you have class MapAsString extends DataMap. Next have a new class that is a subclass of DataMap called perhaps MapAsLocalTime where MapAsLocalTime extends DataMap.

Bonus points: make your parent class DataMap abstract and provide a single abstract method you must implement. that uses Generics to return a List<String, T>. You can have a constructor that takes a T (generic type) which defines what type T will be at construction time. If this seems too hard, perhaps just have it return anything using the wildcard ?… so getter returns List<String, ?> – here ? can an object of any type



Source: stackoverflow