2015-02-23 6 views
1

Я новичок в искусстве разработки свободно распространяемых интерфейсов. У меня есть цепочка классов-конструкторов, которые реализуют интерфейсы, и как интерфейсы, так и реализации компоновщика принимают параметры самореферентного типа.При попытке создать экземпляр самореферентного универсального класса, как вы обрабатываете параметр типа самонаведения

Примечание: Это связано с моим previous question, в котором я попытался разработать интерфейсы немного по-другому, прежде чем пытаться этот подход, в котором интерфейсы принимают самоссылающегося параметр типа, а также:

Вот интерфейс:

public interface ILoadableBuilder<C extends ILoadable,T extends ILoadableBean, B extends ILoadableBuilder<C,T,B>> { 
    T getState(); 
    B setComponentClass(final Class<C> componentClass); 
    B setDriver(final WebDriver driver); 
    B setLoadTimeoutInSeconds(final @Nonnegative int loadTimeoutInSeconds); 
    B setEnumerator(final IEnumeratorBean<? extends IEnumerable<?>,?> enumerator); 
} 

Вот реализация, которая также принимает параметр самореферентного типа. Причина, по которой реализация класса принимает этот параметр, заключается в том, что я хочу, чтобы он был расширяемым, чтобы другие разработчики могли затем расширить этот класс и наследовать все его поведение, и что сеттеры могут быть вызваны в любом порядке, а тип возврата будет верным:

public class LoadableBuilder<C extends ILoadable,T extends ILoadableBean,B extends ILoadableBuilder<C,T,B>> implements 
     ILoadableBuilder<C,T,B> { 

    private final T componentBean; 
    private IEnumeratorBean<? extends IEnumerable<?>,?> enumerator; 
    private Class<C> componentClass; 

    public LoadableBuilder(final T componentBean) { 
     this.componentBean = componentBean; 
    } 

    public final T getState() { 
     return componentBean; 
    } 

    public final B setComponentClass(final Class<C> componentClass) { 
     this.componentClass = componentClass; 
     return (B)this; 
    } 

    public final B setDriver(final WebDriver driver) { 
     getState().setDriver(driver); 
     return (B)this; 
    } 

    public final B setLoadTimeoutInSeconds(final int loadTimeoutInSeconds) { 
     getState().getLoadTimeoutInSeconds(); 
     return (B)this; 
    } 

    public B setEnumerator(final IEnumeratorBean<? extends IEnumerable<?>,?> enumerator) { 
     this.enumerator = enumerator; 
     return (B)this; 
    } 
} 

Мой вопрос: как вы создаете экземпляр этой реализации, не передавая параметр типа классу клиента? Скажем, я хочу объявить переменную-член в классе, который использует конструктор, как так:

public ClientClass<C,T> { 

    private ILoadableBuilder<C,T,_what do I put here????_> builder = new LoadableBuilder<C,T,_what do I put here?????_>(); 

} 

Для метода, это не большая проблема, потому что я могу это сделать:

public <B extends ILoadableBuilder<C,T,B>> void useABuilder() { 
    ILoadableBuilder<C,T,B> builder = new LoadableBuilder<C,T,B>(); 
} 

EDIT:

ClientClass хотел бы построить объект, который реализует интерфейс ILoadable. У меня много разработчиков, которые расширяют ILoadableBuilder для создания объектов, реализующих интерфейсы, которые являются подтипами ILoadable. Идея состоит в том, что я хочу иметь возможность создавать строитель для любого объекта в иерархии наследования под ILoadable, которые сами по себе являются расширяемыми, когда это необходимо.

+0

Зависит от того, как вы собираетесь использовать '' builder' в ClientClass'. –

+0

Я просто хочу использовать его для создания объекта, который нуждается в параметрах типов, указанных в объекте-компиляторе. В принципе, мне нужно создать объект, который реализует ILoadable, а не объект, который имеет подтип ILoadable (для чего потребуются дополнительные сеттеры, которые доступны в построителе, который расширяет LoadableBuilder). – Selena

+0

Я хотел сказать, как вы хотите использовать экземпляр 'builder', который вы создаете в своем' ClientClass'. –

ответ

0

У вас есть два варианта:

  • Make LoadableBuilder не расширяемый, и просто объявить его как

    public class LoadableBuilder<C extends ILoadable, T extends ILoadableBean> 
        implements ILoadableBuilder<C,T,LoadableBuilder<C,T>> 
    
  • Если вы хотите, чтобы она быть расширяемым, а затем сделать его всегда необходимо расширить Это. Пусть LoadableBuilder будет «абстрактным». Определить реализацию скелетного чта только подкласс его без дополнительного материала для «основных» поведений:

    public abstract class LoadableBuilder<C extends ILoadable, 
        T extends ILoadableBean, B extends ILoadableBuilder<C,T,B>> 
        implements ILoadableBuilder<C,T,B> { 
        //... 
    } 
    
    public class BasicLoadableBuilder<C extends ILoadable, T extends ILoadableBean> 
        extends LoadableBuilder<C,T, BasicLoadableBuilder<C,T>> { 
    } 
    
+0

Это на самом деле то, что я закончил делать. – Selena

Смежные вопросы