2010-02-04 5 views
1

J'essayais depuis des jours de savoir si c'est possible, j'ai échoué mais peut-être que c'est possible (je pense que cela devrait être possible).Générer des composants de l'interface utilisateur

Disons que nous avons quelques éléments de l'interface utilisateur similaires avec des hiérarchies Swing + nous allons utiliser les interfaces couramment Fluent Interfaces:

public abstract class Component { 

    ... 

    public abstract Component setName(String name); 

    public abstract String getName(); 

    ... 

} 

public abstract class Panel extends Component { 
    .... 
} 

public abstract class TitledPanel extends Panel { 
    .... 

    public abstract TitledPanel setTitle(String title); 

    public abstract String getTitle(); 
} 

Est-il possible, en utilisant générique pour pouvoir écrire quelque chose comme ça? Set12 doit renvoyer un TitledPanel au lieu de Component pour pouvoir lier ces appels.

Ceci est juste un exemple simple, mais l'idée est une fois que j'ai un objet de type T tout appel à une méthode couramment d'un superclasse pour retourner le type T.

Edit 1: J'oublié d'exclure la partie en remplaçant les méthodes et en renvoyant un type covariant :) Je veux juste des génériques, si c'est possible en effet.

Répondre

1

Je ne suis pas vraiment sûr si vous pourriez réaliser ceci avec des génériques. Qu'est-ce que vous pouvez faire est quelque chose comme ceci:

public abstract class Component { 

private String name; 

public Component setName(String name) { 
    this.name = name; 
    return this; 
} 

public String getName() { 
    return name; 
} 

}

public abstract class Panel extends Component { 

}

public class TitledPanel extends Panel { 

private String title; 

public TitledPanel setTitle(String title) { 
    this.title = title; 
    return this; 
} 

@Override 
public TitledPanel setName(String name) { 
    super.setName(name); 
    return this; 
} 

public String getTitle() { 
    return title; 
} 

}

Maintenant new TitledPanel().setName("panel").setTitle("Title"); travaillera

2

Tout d'abord, je suggère d'utiliser seulement ensemble rencontré hods, et en laissant tomber l'ensemble.

Vous pouvez utiliser des types de retour covariant, mais cela signifie que vous devez remplacer chaque méthode dans chaque classe dérivée. Cependant, cela implique beaucoup de code très fastidieux.

public abstract class Component { 
    ... 
    public Component name(String name) { 
     this.name = name; 
     return this 
    } 
} 

public abstract class Panel extends Component { 
    ... 
    public Panel name(String name) { 
     super.name(name); 
     return this; 
    } 
} 

Ajout d'un paramètre THIS générique, comme ENUM, rend la mise en œuvre plus facile, mais le code client peut avoir besoin d'ajouter un <?> dans les déclarations.

public abstract class Component<THIS extends Component<THIS>> { 
    ... 
    protected abstract THIS getThis(); 
    ... 
    public THIS name(String name) { 
     this.name = name; 
     return this 
    } 
} 

public abstract class Panel<THIS extends Panel<THIS>> extends Component<THIS> { 
    ... 
} 

public class TitledPanel extends Panel<TitledPanel> { 
    ... 
    public TitledPanel getThis() { 
     return this; 
    } 
} 

Une alternative consiste à utiliser l'idiome à double renfort.

new TitledPane() {{ 
    name("panel"); 
    title("Title"); 
}} 
+0

« Tout d'abord, je suggère d'utiliser uniquement des méthodes ensemble, et laisser tomber le jeu. » - n'a pas compris cette partie. –

+0

Quelle partie? Je suggère de ne pas avoir de méthodes - elles sont inutiles. Je suggère également de ne pas utiliser le préfixe 'set' parce qu'il est moche et inutile. –

+0

Vous devez disposer de méthodes pour avoir accès à ces membres. Eh bien, définir et obtenir un sens et c'est aussi une convention de nommage de Sun: http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html Pas que Sun n'a pas de règles brisées, mais ces règles simples ont du sens, au moins pour moi. –

1

Dans votre TiltedPanel (qui ne peut être abstraite par la manière, si vous voulez nouveau vers le haut), vous pouvez remplacer les méthodes abstraites dans des composants et changer le type de retour. Le type de retour ne fait pas partie de la signature de méthode, vous pouvez le mettre en œuvre avec un autre type de retour:

public class Test 
{ 
    public static void main(String[] args) 
    { 
     TiltedPanel p = new TiltedPanel().setName("panel").setTitle("title"); 
     System.out.println("name = " + p.getName()); 
     System.out.println("title = " + p.getTitle()); 
    } 
} 

abstract class Component 
{ 
    public abstract Component setName(String name); 

    public abstract String getName(); 
} 

abstract class Panel extends Component 
{ 
} 

class TiltedPanel extends Panel 
{ 
    private String title; 
    private String name; 

    public TiltedPanel setName(String name) 
    { 
     this.name = name; 
     return this; 
    } 

    public String getName() 
    { 
     return this.name; 
    } 

    public TiltedPanel setTitle(String title) 
    { 
     this.title = title; 
     return this; 
    } 

    public String getTitle() 
    { 
     return this.title; 
    } 
} 
+0

En effet, c'est possible, mais je le voudrais sans types covariants :) –

Questions connexes