2016-09-18 9 views
1

これは初めての投稿ですが、問題が発生しています。 私は現在のヘッダとAbstractDeviceクラスがある:Java抽象、ジェネリックス、およびビルダー

public abstract class AbstractDevice<T extends AbstractDevice.Builder<T>> implements Device 

をこのクラスは、ヘッダと、ネストされたビルダーのクラスがあります

public static abstract class Builder<T> 

Iはまた、ヘッダとAbstractPeripheralクラスを持っています

public abstract class AbstractPeripheral<T extends AbstractPeripheral.Builder<T>> extends AbstractDevice<AbstractPeripheral.Builder> 

このクラスには、次のヘッダーを持つ独自のネストされたビルダークラスがあります。

public static abstract class Builder<T> extends AbstractDevice.Builder<Builder>. 

私の目標は、AbstractPeripheralでAbstractDeviceを拡張し、AbstractPeripheralのBuilderでAbstractDeviceを拡張することです。コンパイルしようとしたときしかし、私はこのエラーを取得しています:

型引数uxb.AbstractPeripheral.Builderは、すべてのヘルプは高く評価され、型変数T.

の範囲内ではありません。おかげ 抽象デバイス:

package uxb; 

import java.util.List; 
import java.util.Optional; 
import java.util.ArrayList; 
import java.math.BigInteger; 


public abstract class AbstractDevice<T extends AbstractDevice.Builder<T>>  
implements Device{ 

public static abstract class Builder<T>{ 

private Integer version; 

private Optional<Integer> productCode; 

private Optional<BigInteger> serialNumber; 

private List<Connector.Type> connectors; 

public Builder(Integer version){ 
    this.version = version; 
} //end constructor method 


public T productCode(Integer productCode){ 
    if(productCode != null){ 
    this.productCode = Optional.of(productCode); 
    } //end if statement 
    else{ 
    this.productCode = Optional.empty(); 
    } //end else statement 
    return getThis(); 
} //end method productCode() 

public T serialNumber(BigInteger serialNumber){ 
    if(serialNumber != null){ 
    this.serialNumber = Optional.of(serialNumber); 
    } //end if statement 
    else{ 
    /*Class has a static field for ZERO value*/ 
    this.serialNumber = Optional.empty(); 
    } //end else statement 
    return getThis(); 
} //end method serialNumber() 


public T connectors(List<Connector.Type> connectors){ 
this.connectors = connectors; 
return getThis(); 
} //end method connectors 


protected abstract T getThis(); 


protected List<Connector.Type> getConnectors(){ 
    return connectors; 
} //end method getConnectors() 


protected void validate(){ 
    if(version == null){ 
    throw new NullPointerException("Cannot be validated"); 
    } 
} //end method validate() 

} //end nested abstract class Builder 


private final Integer version; 

private final Optional<Integer> productCode; 


private final Optional<BigInteger> serialNumber; 

private final List<Connector.Type> connectors; 

private final List<Connector> connectorObjects; 


protected AbstractDevice(Builder<T> builder){ 
    this.version = builder.version; 
    this.productCode = builder.productCode; 
    this.serialNumber = builder.serialNumber; 
    this.connectors = builder.connectors; 
    ArrayList<Connector> temp = new ArrayList<Connector>(); 
    for(int i = 0; i < connectors.size(); i++){ 
    temp.add(new Connector(this, i, connectors.get(i))); 
    } //end for loop 
    connectorObjects = temp; 
} //end constructor method 



public Optional<Integer> getProductCode(){ 
return productCode; 
} //end method getProductCode() 


public Integer getConnectorCount(){ 
/*Not Implemented Yet*/ 
return 0; 
} //end method getConnectorCount() 



public Optional<BigInteger> getSerialNumber(){ 
return serialNumber; 
} //end method getSerialNumber() 


public Integer getVersion(){ 
return version; 
} //end method getVersion() 

public List<Connector> getConnectors(){ 
return new ArrayList<Connector>(connectorObjects); 
} //end method getConnectors() 


public Connector getConnector(int index){ 
    if(! getConnectors().isEmpty()){ 
    return getConnectors().get(index); 
} //end if statement 
else{ 
    return null; 
} //end else statement 
} //end method getConnector() 

} //end abstract class AbstractDevice 

要約ペリフェラル: パッケージuxb。

import java.util.List; 

public abstract class AbstractPeripheral<T extends 
AbstractPeripheral.Builder<T>> extends 
AbstractDevice<AbstractPeripheral.Builder>{ 

public static abstract class Builder<T> extends 
AbstractDevice.Builder<Builder>{ 

protected void validate(){ 
    super.validate(); 
    if(getConnectors().equals(null)){ 
    throw new IllegalStateException("Cannot be validated"); 
    } //end if statement 
    if(checkTypes(getConnectors())){ 
    throw new IllegalStateException("Cannot be validated"); 
    } //end if statement 
} //end method 

private boolean checkTypes(List<Connector.Type> types){ 
    for(Connector.Type type: types){ 
    if(type != Connector.Type.PERIPHERAL){ 
     return false; 
    } //end if statement 
    } //end for each loop 
    return true; 
} //end method checkTypes 

public Builder(Integer version){ 
    super(version); 
} //end constructor method 
} //end nested class Builder 

public AbstractPeripheral(Builder<T> builder){ 
super(builder); 
} 
} //end class AbstractPeripheral 

ハブ: パッケージuxb;

public class Hub extends AbstractDevice<Hub.Builder>{ 

    public static class Builder extends AbstractDevice.Builder<Builder>{ 

public Builder(Integer version){ 
    super(version); 
} //end constructor method 

public Hub build(){ 
validate(); 
return new Hub(getThis()); 
} //end method build() 

protected Builder getThis(){ 
    return this; 
} //end method getThis() 

protected void validate(){ 
    super.validate(); 
    if(!(super.getConnectors().contains(Connector.Type.COMPUTER))){ 
    throw new IllegalStateException("Cannot be validated"); 
    } //end if statement\ 
    if(!(super.getConnectors().contains(Connector.Type.PERIPHERAL))){ 
    throw new IllegalStateException("Cannot be validated"); 
    } //end if statement 
} //end validate() 
} //end nested class Builder 

private Hub(Builder builder){ 
super(builder); 
} //end constructor method 

public DeviceClass getDeviceClass(){ 
return DeviceClass.HUB; 
} //end method getDeviceClass() 


} //end class Hub 
+0

実際のコードを掲載することはできますか? – nitinsh99

+0

抽象オーバーフロー –

+0

'' – Kelvin

答えて

1

あなたは本当にビルダー上のパラメータとして、建設されたクラス、ビルダーの両方を使用する必要があります。ビルド中のオブジェクトはではありませんが、はビルダーについて知る必要はありません。したがって、パラメータとして必要としません。

Apache Brooklynとjcloudsを含むいくつかのオープンソースプロジェクトでこのパターンまたはわずかなバリエーションを使用しました。

次のように、あなたの例から、親クラスを変更します。内蔵されたオブジェクトを返します。私も抽象build()方法を追加しました

public abstract class AbstractDevice implements Device { 
    public static abstract class Builder<T, B> { 
     public abstract B self(); 
     public abstract T build(); 
     public B example(String value) { 
      // do something with value 
      return self(); 
     } 
    } 
} 

注意を。 self()メソッドが必要なのは、ビルダーメソッドがthisを返す場合、間違ったタイプになるからです。代わりに、各ビルダーメソッドは、​​メソッドのように、return self();で終了する必要があります。そして、子供は次のようになります。

public abstract class AbstractPeripheral extends AbstractDevice { 
    public static abstract class Builder<T, B> extends AbstractDevice.Builder<T, B> { 
    } 
} 

あなたがTBジェネリックパラメータは、クラスの種類とそれぞれのビルダーの種類を指すために使用されていることがわかります。したがって、これらを使用する具体的なクラスを作るために、このようなものを作成する必要があります。

public class Hub extends AbstractPeripheral { 
    public static class Builder extends AbstractPeripheral.Builder<Hub, Builder> { 
     public static final Builder builder() { 
      return new Builder(); 
     } 
     public Builder self() { 
      return this; 
     } 
     public Hub build() { 
      return new Hub(); 
     } 
    } 
} 

また、これは正しいBuilderクラスのインスタンスを返す静的builder()方法を、持っている、あなたも直接コンストラクタを呼び出すことができますあなたも同様にしたい。 build()メソッドは具象クラスを作成して返します。self()メソッドはここにを返して正しいタイプのthisを返します。

一緒にすべてを置く、次のように我々はHubオブジェクトを作成するためにこれを使用することができます:それは実際にHub#self()を呼び出すので、AbstractDevice.Builder#example(String)方法が正しい型を返すこと

Hub hub = Hub.Builder.builder() 
     .example("something") 
     .build(); 

注意を、とbuild()Hubの具体的なインスタンスを返します。予想通り。

これから苦痛を払い、繰り返される定型文を削除するには、Google AutoValueプロジェクトを試してみてください。私たちは現在jcloudsに切り替えています。

+0

本当にありがとうございました! –

+0

型パラメータ*のみ*ビルドするクラスではなく、ビルダーに行く必要があることに注意してください。私はこれをクリアするための答えを更新しました – grkvlt

関連する問題