nus-cs2030 / 2021-s2

2 stars 2 forks source link

AY2021 Sem 1: Q2 Generics #377

Closed somenobody98 closed 3 years ago

somenobody98 commented 3 years ago

Summary

Jshell can't find my method?

Description

Does anyone know why jshell cannot find the method replace? I do not think my solution has any issues? Also imported everything Or is it my test case producing the problem? Thank you!

My Answer:

image

Question:

image

lyntan01 commented 3 years ago

When you wrote the function replace in jshell, did it give something like

created method replace(List<? extends T>,List<? super T>,BiPredicate<? extends T,? super T>), however, it cannot be referenced until class T is declared

If it did, try adding a at the start of the method signature

somenobody98 commented 3 years ago

Ya, I just tried it and it did. I understand why jshell would do that, but how do I go about this? And what do you mean by "adding a at the start of the method signature"?

JYLim99 commented 3 years ago

I believe lyntanrambutan suggest declaring <T> at the start of the method. So it should be something like <T> void replace(List<? extends T> ...) since currently the variable T is not being declared within the method/class

somenobody98 commented 3 years ago

I believe lyntanrambutan suggest declaring <T> at the start of the method. So it should be something like <T> void replace(List<? extends T> ...) since currently the variable T is not being declared within the method/class

Ahh I see, I just tried it but now I am getting this which seems weird? image

eugenecyh94 commented 3 years ago

Hi, the complication seem arise from the technicalities behind the design of jshell for testing.

To overcome this you can try creating a class consisting of the replace method to test if your method works.

In addition you might need to define your src list type to only extend dst type <? extends T>, and keep dst list type to be fixed , as the qn is asking for values in dst to be replaced by src list based on the criteria, and no need for the other way round. In this case a bipredicate might also not be necessary and a predicate or comparator will suffice.

My 2 cents, hope it helps somewhat :)

elitanzc commented 3 years ago

Hello! I met this problem too when trying this question. I think it might got to do with the pecs principle coz the solution worked when I tried <T> void replace(List<? extends T> src, List<T> dst, BiPredicate<? super T, ? super T> pred) instead. The pred is a consumer, so both arguments must be ? super T, and for src it only produces so it must be ? extends T. For dst it is both a producer (for the pred function) and a consumer (of src) so using <T> will do.

ruthkangyr commented 3 years ago

Hello! I met this problem too when trying this question. I think it might got to do with the pecs principle coz the solution worked when I tried <T> void replace(List<? extends T> src, List<T> dst, BiPredicate<? super T, ? super T> pred) instead. The pred is a consumer, so both arguments must be ? super T, and for src it only produces so it must be ? extends T. For dst it is both a producer (for the pred function) and a consumer (of src) so using <T> will do.

can I ask how did your test case look like in this case?

seannzx commented 3 years ago

Not sure if this is correct but heres how I did it

static <T> void replace(List<? extends T> src, List<T> dst, BiPredicate<? super T, ? super T> pred) {
    if (src.size() == dst.size()) {
        for (int i = 0; i < src.size(); i++) {
            if (pred.test(src.get(i), dst.get(i))) {
                dst.set(i, src.get(i));
            }
        }
    }
}

As for the test cases

List<Number> destination = new ArrayList<>(List.of(1, 2, 3));
List<Integer> source = new ArrayList<>(List.of(4, 5, 6));

System.out.println(destination);
replace(source, destination, (src, dst) -> true);
System.out.println(destination);

I believe using Double/Integer as the different T types are not compatible as if you look at the class hierarchy, both Double/Integer are subclasses of Number. So it will actually throw an error when you try to insert a type Integer into the List<Double> destination

somenobody98 commented 3 years ago

Hello! I met this problem too when trying this question. I think it might got to do with the pecs principle coz the solution worked when I tried <T> void replace(List<? extends T> src, List<T> dst, BiPredicate<? super T, ? super T> pred) instead. The pred is a consumer, so both arguments must be ? super T, and for src it only produces so it must be ? extends T. For dst it is both a producer (for the pred function) and a consumer (of src) so using <T> will do.

Hi, thanks for the explanation!! I get it!