Can someone please explain the following lines of code to me:
import org.apache.beam.sdk.Pipeline;
[..]
Pipeline p = Pipeline.create(options);
p.apply(TextIO.read().from("gs://apache-beam-samples/shakespeare/*"))
.apply("ExtractWords", ParDo.of(new DoFn<String, String>() {/* etc */}
What I don't get is why this compiles. Apply method in Pipeline returns a T extends POutput. Interface POutput does not have any apply method.
In this case, it just so happens that TextIO.read().from(...) returns a PCollection as POutput, and THAT has an apply method.
But as far as the Pipeline contract goes, we know that just a POutput will be returned. So how does the compiler get to check the type of the argument passed to the first apply? From what I remember from when I was coding Java, that would be seen only at runtime.