2017-02-14 2 views
3

Ich habe eine abstrakte Klasse, die eine abstrakte Methode enthält, die einen generischen Typ zurückgibt. können sagenWie überschreibt Methoden mit generischen Rückgabetyp in Java im Falle von Vererbung auf mehreren Ebenen

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(); 
    } 
} 

Jetzt habe ich eine Klasse Sample1 haben, die diese Klasse erweitert und implementiert die Methode copyBuilder()

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 
    } 
} 

Es gibt eine andere Klasse Sample2, die eine Unterklasse von Sample1 ist. Wenn ich versuche, die Methode copyBuilder() in dieser Klasse zu überschreiben, bekomme ich Probleme im Rückgabetyp.

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 sagt die Methode kollidiert mit dem in der übergeordneten Klasse und versuchte inkompatibel Rückgabetyp zu verwenden.

Kann jemand vorschlagen, wie Sie die Methode copyBuilder() in Sample2 implementieren, so dass Sample2.Builder zurückgegeben wird.

+0

Sie in dieser Frage interessiert sein bezüglich generischer Rückgabetyp es in Java: http://stackoverflow.com/questions/36654841/java-compile-error-in-method-with-generic-return-type – jaco0646

Antwort

1

Ich mag keinen Teil B extends SampleBuilder<T, B>. Warum ist es sogar nützlich, sich selbst zu referenzieren?

Auf jeden Fall können Sie es, wenn Sie

SampleBuilder<Sample1,Sample1.Builder> copyBuilder() ändern funktioniert

zu

SampleBuilder<? extends Sample1, ?> copyBuilder()

Ein komplettes Beispiel unter

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

Ja, das funktioniert !! :) Aber wie? – bushra

+0

Dies bedeutet, eine Klasse ist eine Unterklasse von sich selbst, wenn ich copyBuilder() von einem Objekt von Sample1 aufrufen, dann gibt Sample1.Builder, die typecasted zu SampleBuilder .... bedeutet das, Sample1 erweitert Sample1? – bushra

+0

@bushra Das Ändern von 'Sample1.Builder' in'? 'Macht' copyBuilder() 'Methode überschreibbar. Sie können eine Methode nicht überschreiben und den Rückgabetyp anders oder allgemeiner gestalten. –

2

Sie brauchen hier keine Generika. Das funktioniert perfekt:

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

Danke für Ihre Antwort. – bushra

+0

Aber ich brauche Generika hier. lassen Sie mich die detaillierte Implementierung des Erbauers geben. – bushra

Verwandte Themen