2010-02-04 3 views
1

Я пытался в течение нескольких дней выяснить, возможно ли, я потерпел неудачу, но, возможно, это возможно (я думаю, это должно быть возможно).Создать компоненты пользовательского интерфейса

Скажем, у нас есть несколько компонентов пользовательского интерфейса, аналогичные с Свинг иерархий + мы будем использовать беглые интерфейсы 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(); 
} 

Можно ли, используя общий, чтобы иметь возможность написать что-то подобное?

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

setName должен возвращать TitledPanel вместо Component, чтобы иметь возможность связывать эти вызовы.

Это простой пример, но идея состоит в том, как только у меня есть объект типа T любого вызова к любому беглой методе суперкласса для возвращения типа T.

Edit 1: Я забыл, чтобы исключить часть с переопределением методов и возвратом ковариантных типов :) Я хочу просто простые дженерики, если это действительно возможно.

ответ

1

Я не уверен, что вы могли бы добиться этого с помощью дженериков. Что вы можете сделать что-то вроде этого:

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

}

Теперь new TitledPanel().setName("panel").setTitle("Title"); будет работать

2

Во-первых, я предлагаю использовать только набор встретился hods, и падение набора.

Вы можете использовать типы возвращаемых ковариантов, но это означает переопределение каждого метода в каждом производном классе. Тем не менее, это связано с очень утомительным кодом.

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

Добавление общего THIS параметра, так как перечисление, делает реализацию легче, но клиентский код может понадобиться добавить <?> в объявлениях.

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

Альтернативой является использование Идиомы двойной бреши.

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

«Во-первых, я предлагаю использовать только методы набора и сбросить набор». - не понял эту часть. –

+0

Какая часть? Я предлагаю не получать методы - они бесполезны. Я также предлагаю не использовать префикс 'set', потому что он уродливый и ненужный. –

+0

Вам нужно иметь методы доступа к этим членам. Ну, установить и получить имеет смысл, и это также соглашение об именах от Sun: http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html Не то, чтобы у Солнца не было никаких нарушенных правил, но эти простые правила имеют смысл, по крайней мере для меня. –

1

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

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

Действительно, это возможно, но я бы хотел его без ковариантных типов :) –

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