mercredi 12 mai 2021

How to structure code to prevent incompatible capture of ? extends _?

I was wondering what is the best way to structure code to ensure compiler knows in very simple cases that passed variable is of correct type. I have created very simple code where class O has its execute method execute that accepts some kind of payload (that extends class P) and performs some kind of operation. The thing is that I do not know how to structure my code to ensure that compiler knows what kind of specific payload I am passing to execute method. First thing that came to my mind was to introduce method that would return classType of used payload just to came to realization that it is of no use because I am trying to pass some potentially different type of payload to execute method that accepts specific payload.

By the end of the day I could just use reflection but I was wondering how to solve this kind of problem without the use of reflection - whether there is some kind of pattern to solve this problem or some other way to structure my code,...

I know that this kind of simple in terms of printing payload can be solved by introducing method that would print desired payload,... but let's say that I would like to do something more than just printing to console.

Thanks in advance!

import java.util.List;

class Scratch {

    public static abstract class O<I extends P> {
        public abstract void execute(I payload);
    }

    public static class O1 extends O<P1> {
        @Override
        public void execute(P1 payload) {
            System.out.println(payload.a);
        }
    }

    public static class O2 extends O<P2> {
        @Override
        public void execute(P2 payload) {
            System.out.println(payload.b);
        }
    }

    public static abstract class P {
        abstract Class<? extends P> getClassType();
    }

    public static class P1 extends P {
        public String a = "a";

        @Override
        Class<? extends P> getClassType() {
            return P1.class;
        }
    }

    public static class P2 extends P {
        public Integer b = 1;

        @Override
        Class<? extends P> getClassType() {
            return P2.class;
        }
    }

    public static void main(String[] args) {
        List<O<? extends P>> os = List.of(new O1(), new O2());
        List<P> ps = List.of(new P1(), new P2());

        for (int i = 0; i < 2; i++) {
            var p = ps.get(i);
            // this line would prevent compilation
            os.get(i).execute(p);
            // this line would also prevent compilation
            os.get(i).execute(p.getClassType().cast(p));
        }
    }
}

Aucun commentaire:

Enregistrer un commentaire