2017-02-14 4 views
3

私はジェネリック型を返す抽象メソッドを含む抽象クラスを持っています。 は今、私はサンプル1のサブクラスである別のクラスサンプル2があり、このクラスを拡張し、メソッドcopyBuilderを(実装するクラスサンプル1)多値継承の場合にJavaで汎用戻り型のメソッドをオーバーライドする方法

public class Sample1 extends AbstractSample { 
    //class members 

    @Override 
    public AbstractSample.SampleBuilder<Sample1,Sample1.Builder> copyBuilder()  { 
    return new Sample1.Builder(this); 
    } 

    //other methods 
    //builder 
    public static class Builder extends SampleBuilder<Sample1,Builder> { 
    //implementation 
    //containing members and methods 
    } 
} 

を持って

abstract class AbstractSample{ 
    //class members 

    //this method needs to be overriden 
    public abstract SampleBuilder<? extends AbstractSample,?> copyBuilder(); 

    //other methods 
    //builder 
    public static abstract class SampleBuilder<T extends AbstractSample, B extends SampleBuilder<T,B>> { 
    //properties 
    private String as; 

    public SampleBuilder(AbstractSample object) { 
     this.as = object.as; 
    } 

    public B as(String as) { 
     this.as = as; 
     return (B)this; 
    } 

    public abstract T build(); 
    } 
} 

を言うことができます。 このクラスのcopyBuilder()メソッドをオーバーライドしようとすると、戻り値の型で問題が発生しています。

class Sample2 extends Sample1 { 
    //class members 

    // I am not allowed to implement this as below 
    @Override 
    public AbstractSample.SampleBuilder<Sample2,Sample2.Builder> copyBuilder() { 
    return new Sample2.Builder(this) ; 
    } 

    //other methods 
    //builder 
    public static class Builder extends SampleBuilder<Sample2,Builder> { 
    //implementation 
    //containing members and methods 
    } 
} 

IntelliJは、メソッドが互換性のない戻り値の型を使用しようとすると、スーパークラスのメソッドと衝突すると説明しています。

誰でも、Sample2でメソッドcopyBuilder()を実装し、Sample2.Builderを返す方法を提案できますか?

+0

を下回っているあなたは、この問題に興味がある可能性があり、それを動作させることができますジェネリックリターンtyp Javaの場合:http://stackoverflow.com/questions/36654841/java-compile-error-in-method-with-generic-return-type – jaco0646

答えて

1

私は一部が好きではありませんB extends SampleBuilder<T, B>。それ自体を参照することはなぜ有用なのでしょうか?

とにかくあなたが

SampleBuilder<? extends Sample1, ?> copyBuilder()

SampleBuilder<Sample1,Sample1.Builder> copyBuilder()

を変更した場合、完全な例は

public class Test { 
abstract static class AbstractSample { 

    private String as; 

    //this method needs to be overriden 
    public abstract SampleBuilder<? extends AbstractSample, ?> copyBuilder(); 

    public static abstract class SampleBuilder<T extends AbstractSample, B extends SampleBuilder<T, B>> { 

     private String as; 

     public SampleBuilder(AbstractSample object) { 
      this.as = object.as; 
     } 

     public B as(String as) { 
      this.as = as; 
      return (B) this; 
     } 

     public abstract T build(); 
    } 
} 

static class Sample1 extends AbstractSample { 

    @Override 
    public SampleBuilder<? extends Sample1, ?> copyBuilder() { 
     return new Builder(this); 
    } 

    public static class Builder extends SampleBuilder<Sample1, Builder> { 

     public Builder(Sample1 sample1) { 
      super(sample1); 
     } 

     @Override 
     public Sample1 build() { 
      return null; 
     } 
    } 
} 

static class Sample2 extends Sample1 { 

    @Override 
    public SampleBuilder<? extends Sample2, ?> copyBuilder() { 
     return new Builder(this); 
    } 

    public static class Builder extends SampleBuilder<Sample2, Builder> { 

     public Builder(Sample2 sample2) { 
      super(sample2); 
     } 

     @Override 
     public Sample2 build() { 
      return null; 
     } 
    } 
} 
} 
+0

はい、これは動作します! :)しかし、どのように? – bushra

+0

これは、クラスがそれ自身のサブクラスであることを意味します。私がSample1のオブジェクトからcopyBuilder()を呼び出すと、SampleBuilderに型キャストされているSample1.Builderを返します。 extends Sample1、?> ....これは、Sample1がSample1を拡張することを意味しますか? – bushra

+0

@bushra 'Sample1.Builder'を'? 'に変更すると' copyBuilder() 'メソッドがオーバーライド可能になります。メソッドをオーバーライドしたり、戻り値の型を違うまたはより一般的にすることはできません。 –

2

ここにジェネリックは必要ありません。これは完全に動作します:

abstract class AbstractSample { 

    public abstract SampleBuilder copyBuilder(); 

    public static abstract class SampleBuilder { 
     public abstract AbstractSample build(); 
    } 
} 

public class Sample1 extends AbstractSample { 

    @Override 
    public Sample1.Builder copyBuilder() { 
     return new Sample1.Builder(this); 
    } 

    public static class Builder extends SampleBuilder { 
     public Builder() { } 
     public Builder(Sample1 d) { } 

     @Override 
     public Sample1 build() { 
      return null; 
     } 
    } 
} 

class Sample2 extends Sample1 { 
    @Override 
    public Sample2.Builder copyBuilder() { 
     return new Sample2.Builder(this) ; 
    } 

    public static class Builder extends Sample1.Builder { 
     public Builder(Sample2 d) { } 

     @Override 
     public Sample2 build() { 
      return null; 
     } 
    } 
} 
+0

あなたの答えをありがとう。 – bushra

+0

しかし私はここにジェネリック薬が必要です。ビルダーの詳細な実装を教えてください。 – bushra

関連する問題