Общий тип, ограниченный другим общим - PullRequest
2 голосов
/ 19 января 2011

Предположим, у меня есть это:

interface Shape {}
interface Square extends Shape {}
interface Circle extends Shape {}

interface ShapeBuilder<S extends Shape> {}

Я хочу что-то вроде этого:

class ShapeBuilderFactory<SB extends ShapeBuilder> {
    SB<Square> getSquareBuilder(){...}
    SB<Circle> getCircleBuilder(){...}
}

Этот код не компилируется (потому что ShapeBuilder является необработанным типом), но я надеюсь,Вы понимаете идею.Можно ли сделать что-то подобное в Java?Как?

(реальная проблема не в строителях фигур и фабриках, я использовал этот пример для простоты)

Редактировать (больше контекста)

У меня разные строители:

interface RegularShapeBuilder<S extends Shape> extends ShapeBuilder<S> {}
interface FunnyShapeBuilder<S extends Shape> extends ShapeBuilder<S> {}

class RegularSquareBuilder extends RegularShapeBuilder<Square> {}
class FunnySquareBuilder extends FunnyShapeBuilder<Square> {}
class RegularCircleBuilder extends RegularShapeBuilder<Circle> {}
class FunnyCircleBuilder extends FunnyShapeBuilder<Circle> {}

И я хочу, чтобы завод делал такие вещи:

ShapeBuilderFactory<FunnyShapeBuilder> funnyShapeBuilderFactory = ...;
FunnyShapeBuilder<Square> funnySquareBuilder = funnyShapeBuilderFactory.getSquareBuilder();

Ответы [ 3 ]

2 голосов
/ 19 января 2011
class ShapeBuilderFactory<S extends Shape, SB extends ShapeBuilder<S>> {

Хотя вы можете подумать, нужно ли вам, чтобы оно вообще было общим.

1 голос
/ 19 января 2011

Я не уверен, почему у вас просто не было бы:

class ShapeBuilderFactory {
    ShapeBuilder<Square> getSquareBuilder(){...}
    ShapeBuilder<Circle> getCircleBuilder(){...}
}

Редактировать

Итак, если вам действительно нужен подтип ShapeBuilder на вашей фабрике, вам нужно объявить каждый из них:

class ShapeBuilderFactory<SqB extends ShapeBuilder<Square>, 
                          CiB extends ShapeBuilder<Circle>> {
    SqB getSquareBuilder(){...}
    CiB getCircleBuilder(){...}
}

Так что вам придется объявить это как:

ShapeBuilderFactory<FunnySquareBuilder, FunnyCircleBuilder> funnyShapeBuilder = ...

Но вы сможете сказать:

FunnyShapeBuilder<Square> funnySquareBuilder = funnyShapeBuilderFactory.getSquareBuilder();

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

Если бы это был мой код, я бы использовал определение ShapeBuilderFactory, которое я изначально написал, и создавал его с помощью забавных или обычных сборщиков.Разве смысл в том, чтобы эти интерфейсы действительно их использовали?

0 голосов
/ 19 января 2011

Бросьте дженерики на фабричный класс, сделайте что-то вроде:

interface Shape {}
interface Square extends Shape {}
interface Circle extends Shape {}

interface ShapeBuilder<S extends Shape> {}

class ShapeBuilderFactory {
    ShapeBuilder<Square> getSquareBuilder(){...}
    ShapeBuilder<Circle> getCircleBuilder(){...}
}
...