How to replace run-time instanceof check with compile-time generics validation

前端 未结 6 904
有刺的猬
有刺的猬 2021-01-22 11:52

Got a little puzzle for a true Java Generics specialist... ;)

Let\'s say I have the following two interfaces:

interface Processor {
    void process(Foo          


        
6条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-01-22 12:25

    This is uglier than I thought. My take:

    interface Processor> {
        void process(F foo);
    }
    
    interface Foo> {
        Processor getProcessor();
    }
    
    interface SomeFoo extends Foo {
        @Override
        SomeProcessor getProcessor();
    }
    
    interface SomeProcessor extends Processor {
        @Override
        void process(SomeFoo foo);
    }
    

    Now, the following will compile:

    > void process(F foo) {
        foo.getProcessor().process(foo);
    }
    

    but

    void process(Foo foo) {
        foo.getProcessor().process(foo);
    }
    

    doesn't, because the compiler can not know that actual type of the passed foo is a subtype of its type parameter, as somebody could write:

        class Bar implements Foo { ... }
    

    We can work around this by requiring the subtypes of foo to implement a conversion to their type parameter:

    abstract class Foo> {
        abstract Processor getProcessor();
    
        abstract F getThis();
    }
    
    class SomeFoo extends Foo {
        @Override
        SomeFoo getThis() {
            return this;
        }
    
        @Override
        Processor getProcessor() {
            return new SomeProcessor();
        }
    }
    

    Now, we can write:

    > void process(Foo foo) {
        foo.getProcessor().process(foo.getThis());
    }
    

    and invoke this with

    Foo foo = ...;
    process(foo);
    

    To make it easy to use, I recommend moving the helper method into class Foo:

    abstract class Foo> {
        abstract Processor getProcessor();
    
        abstract F getThis();
    
        void processWith(Processor p) {
            p.process(getThis());
        }
    }
    

    Update: I think newaccts updated answer shows a more elegant solution, as it does not need the recursive type bounds.

提交回复
热议问题