Генерировать компоненты пользовательского интерфейса - PullRequest
1 голос
/ 04 февраля 2010

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

Допустим, у нас есть несколько компонентов пользовательского интерфейса, похожих на иерархии Swing + мы будем использовать плавные интерфейсы Свободные интерфейсы :

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

Возможно ли использование generic, чтобы написать что-то подобное?

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 04 февраля 2010

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

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

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, например enum, упрощает реализацию, но клиентскому коду может потребоваться добавить <?> в объявлениях.

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");
}}
1 голос
/ 04 февраля 2010

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

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;
    }
}
1 голос
/ 04 февраля 2010

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

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"); будет работать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...