2011-01-19 1 views
2

générique Supposons que j'ai ceci:Type générique délimité par un autre

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

interface ShapeBuilder<S extends Shape> {} 

Je veux quelque chose comme ceci:

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

Ce code ne compile pas (parce ShapeBuilder est un type brut), mais J'espère que vous comprenez l'idée. Est-il possible de faire quelque chose comme ça dans Java? Comment?

(le vrai problème est pas avec les constructeurs de formes et des usines, je cet exemple pour simplifier) ​​

Modifier (contexte plus)

J'ai différents types de constructeurs:

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

Et je veux l'usine à faire des choses comme ceci:

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

Qu'est-ce que vous essayez de acheive en faisant générique ShapeBuilderFactory? Évidemment, un ShapeBuilder ne peut pas produire à la fois un carré et un cercle, parce que vous avez dit qu'il ne peut produire qu'un seul type. –

+0

J'essaye de rendre la classe d'usine capable de renvoyer différents genres de constructeurs (regularBuilder, funnyBuilder, etc.). Je veux avoir une regularShapeBuilderFactory et une funnyShapeBuilderFactory comme instances de la même classe. – Pomber

+0

Ok, mais pourquoi ont-ils besoin d'exposer le type de constructeur qu'ils utilisent? Les différents types de constructeurs font-ils d'autres choses pour lesquelles vous auriez besoin du sous-type? –

Répondre

1

Je ne sais pas pourquoi vous auriez pas seulement:

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

Modifier

Donc, si vous devez vraiment avoir le sous-type ShapeBuilder dans votre usine, vous devrez déclarer chacun d'eux:

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

vous aurez donc doivent déclarer que:

ShapeBuilderFactory<FunnySquareBuilder, FunnyCircleBuilder> funnyShapeBuilder = ... 

Mais vous serez en mesure de dire

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

Le problème que vous avez est qu'une mise en œuvre de ShapeBuilder ne peut créer un type de forme. C'est comme ça que vous l'avez déclaré.

Si c'était mon code, j'utiliserais la définition ShapeBuilderFactory que j'avais initialement écrite et je l'instancierais avec des builders drôles ou réguliers. N'est-ce pas le point d'avoir ces interfaces les utilisant réellement?

+0

parce que chaque méthode de l'usine renvoie un constructeur générique différent –

+0

Désolé, je l'ai mal formaté de sorte que le et ont été avalés –

+0

Oui, vous avez raison. Mais le vrai code est plus complexe et n'a rien de commun avec les constructeurs, je voulais savoir si Java avait un truc pour résoudre ce problème, mais il semble que ce ne soit pas le cas. En tout cas, j'aime ta solution plus que la mienne (j'ai fait plusieurs classes d'usine). Merci – Pomber

2
class ShapeBuilderFactory<S extends Shape, SB extends ShapeBuilder<S>> { 

Bien que vous pourriez considérer si vous avez besoin qu'il soit générique du tout.

+0

Je ne veux pas que l'usine fonctionne avec un seul type de forme, le constructeur passé à l'usine devrait être générique – Pomber

0

Laissez tomber les génériques de la classe d'usine, faire quelque chose comme:

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

interface ShapeBuilder<S extends Shape> {} 

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