2009-06-18 40 views
6

我剛剛讀了Java 7 preview presentation (pdf),並且在鏈式調用上有一個幻燈片。這是在幻燈片中使用的例子:Java 7中的鏈接調用?

// Construction with setters 
DrinkBuilder margarita = new DrinkBuilder(); 
margarita.add("tequila"); 
margarita.add("orange liqueur"); 
margarita.add("lime juice"); 
margarita.withRocks(); 
margarita.withSalt(); 
Drink drink = margarita.drink(); 

// Construction with chained invocation 
Drink margarita = new DrinkBuilder() 
    .add("tequila") 
    .add("orange liqueur") 
    .add("lime juice") 
    .withRocks() 
    .withSalt() 
    .drink(); 

而且我感慨這個感受。不應該將太多的方法調用鏈接到一個語句中。另一方面,編寫margarita.this()margarita.that()也不太方便。

現在,我從德爾福世界來到Java。在Delphi中有with語言結構。這受到少數人的喜愛並被許多人所厭惡(或者相反?)。我發現with比鏈式調用的思想更優雅(我相信這是基於void方法返回對其已被調用的對象的引用的工作原理 - 這是我不喜歡的部分,因爲void應該返回nothing)。

我將不勝感激的with語言特性被Java被收養,所以示例代碼可以寫像這樣:

Drink margarita = null; 
with (new DrinkBuilder()) { 
    add("tequila"); 
    add("orange liqueur"); 
    add("lime juice"); 
    withRocks(); 
    withSalt(); 
    margarita = drink(); 
} 

我是唯一一個誰願意這樣解決鏈調用?其他人認爲with可能是Java語言的有用擴展? (讓我想起某人關於需要「Java ++」的問題...)

+2

這不僅限於Java 7,您可以通過簡單地在方法中返回「this」來編寫構建器。一個很好的例子是java.lang.StringBuilder。 – 2009-06-18 10:21:59

+5

我認爲問題是Java 7允許鏈接而不返回它,因此改變了方法調用的語義。 – OregonGhost 2009-06-18 10:30:39

回答

12

語句可以在Java中使用匿名類與初始化翻譯:

Drink margarita = new DrinkBuilder() {{ 
    add(「tequila」); 
    add(「orange liqueur」); 
    add(「lime juice」); 
    withRocks(); 
    withSalt(); 
}}.drink(); 

使用這個成語的缺點是有據可查的here

鏈式調用是方法鏈接的別名。這是衆所周知的成語,並與任何版本的Java工作:

class Chained { 

    public Chained withFoo() { 
     // ... 
     return this; 
    } 

    public Chained withBar() { 
     // ... 
     return this; 
    } 
}  

的JDK 7的建議是allowing of chaining method also for void return type

class ChainedJava7 { 

    public void withFoo() { 
     // ... 
    } 

    public void withBar() { 
     // ... 
    } 
}  
+1

當你的答案出現時,我只是寫了關於雙大括號初始化:-) – 2009-06-18 10:32:13

+1

這真的很不錯。 +1 – 2009-06-18 10:45:19

+2

請注意,幾個月前通過JDK7的小語言更改截止日期。 – 2009-06-18 10:47:39

1

我不是這種用法的粉絲with;我更喜歡Python with statement。不過,我同意你的意見void應該是void。在你提供的例子中,如果一個人真的想要鏈接方法調用,他們應該改變他們的方法的返回類型,以便它們是可鏈接的。

+0

嗯,它是無效的。作爲一名製片人,你不會回報任何東西,而你的消費者不會在意接收任何東西(儘管有時他們會這麼做)。你爲什麼要關心?在語義上,沒有任何變化(除了必須輸入太多)。 – 2009-06-18 12:05:37

+0

除了你*正在返回一些東西,並且你正在隱式地這樣做。如果你沒有返回任何東西,那麼你無法調用它的方法。由於這是Java,幾乎所有其他東西都是明確的,所以我寧願讓回報明確。 – 2009-06-18 12:58:55

2

This可能會讓你感興趣。

2

我很喜歡這種形式的with聲明,但我更喜歡的VB版其中:

With testObject 
    .Height = 100 
    .Text = "Hello, World" 
    .ForeColor = System.Drawing.Color.Green 
End With 

正如With塊中的每個屬性仍然必須由.前面你知道找你引用一個Object屬性而不是一個本地變量,從而減少任何命名空間衝突。

如果我們把你的例子:

with (new DrinkBuilder()) { 
    add(「tequila」); 
    add(「orange liqueur」); 
    add(「lime juice」); 
    withRocks(); 
    withSalt(); 
    margarita = drink(); 
} 

有沒有簡單的方法來判斷是否withSalt()DrinkBuilder方法或局部類中的方法。如果你只允許在with塊中允許with -ed對象的方法,那麼我認爲它們變得不太有用。

+0

我的建議是用Salt()作爲Drink Builder的一個方法。如果你發現應用程序沒有做它應該做的,你可以調用this.withSalt();以明確哪些對象的withSalt()方法應該被調用。 – 2009-06-18 10:44:22

1

也許許多對一個對象的調用是一些代碼需要移動的標誌?

+2

不,這是Do One Thing的整個Bean口頭禪的一部分,因爲Java沒有一流的屬性,所以我們必須爲所有事情編寫getter和setter。這就是爲什麼。從Java 7(屬性)中刪除的其他東西。 – 2009-06-18 12:07:38

+0

@darthcoder - 很高興你提到過!我不明白爲什麼自1.0以來它不屬於Java的一部分 – 2009-06-18 12:29:55

1

Joshua Bloch在Effective Java項目#2強烈建議使用Builder,當你有一個構造函數有很多參數。其中一個原因是它可以寫​​成保證構建的對象始終處於一致狀態。它還避免了在構建的對象類中使用複雜的「伸縮構造函數」。還有一點是,如果你希望構建的對象是不可變的(例如,爲了線程安全),它不能有setter方法。