2010-02-04 98 views
1

我想了幾天想弄清楚是否可能,我失敗了,但也許這是可能的(我認爲它應該是可能的)。生成用戶界面組件

比方說,我們有秋千層次+類似的一些UI組件,我們將使用流利的接口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.

編輯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

首先,我建議只使用遇見了點頭,然後放下一套。

您可以使用協變返回類型,但這意味着覆蓋每個派生類中的每個方法。但是,它確實涉及很多非常乏味的代碼。

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

。「首先,我建議只使用一套方法,並且丟棄集」 - 沒有理解這部分。 – 2010-02-04 19:21:16

+0

哪部分?我建議不要使用方法 - 它們是無用的。我也建議不要使用'set'前綴,因爲它是醜陋而且不必要的。 – 2010-02-04 19:48:21

+0

你需要有方法來訪問這些成員。那麼,設置和獲取是有道理的,它也是Sun的命名約定:http://java.sun.com/docs/codeconv/html/CodeConventions.doc8。html 不是說Sun沒有任何違規規則,但這些簡單的規則是有道理的,至少對我而言是這樣。 – 2010-02-04 20:36:22

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

確實,這是可能的,但我希望它沒有covariant類型:) – 2010-02-04 19:25:26