2009-06-18 23 views
6

Tôi vừa đọc một số Java 7 preview presentation (pdf) và có một trang trình bày trên Yêu cầu được ghép nối. Dưới đây là ví dụ được sử dụng trong trang trình bày:Yêu cầu xích trong 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(); 

Và tôi có cảm giác lẫn lộn về điều này. Người ta không nên chuỗi quá nhiều lời gọi phương thức vào một câu lệnh. Mặt khác, viết margarita.this()margarita.that() cũng không thuận tiện.

Bây giờ, tôi đang đến Java từ thế giới Delphi. Và ở Delphi có cấu trúc ngôn ngữ with. Điều này được ấp ủ bởi một vài người và bị ghê tởm bởi nhiều người (hoặc là nó theo cách khác xung quanh?). Tôi thấy with là thanh lịch hơn ý tưởng về yêu cầu xích (mà tôi tin rằng hoạt động trên cơ sở phương pháp void trả về tham chiếu đến đối tượng mà nó đã được gọi - và đây là phần tôi không thích, vì void phải trả về không có gì).

tôi sẽ đánh giá cao tính năng with ngôn ngữ được chấp nhận bởi Java, vì vậy mã ví dụ có thể được viết như sau:

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

Tôi là người duy nhất muốn giải pháp này đến gọi xích? Bất cứ ai khác cảm thấy rằng with có thể là một phần mở rộng hữu ích cho ngôn ngữ Java? (Nhắc tôi về câu hỏi của ai đó về sự cần thiết của "Java ++" ...)

+2

Điều này không giới hạn đối với Java 7, bạn có thể viết trình tạo bằng cách đơn giản trả lại "this" trong phương thức. Một ví dụ tốt là java.lang.StringBuilder. –

+5

Tôi nghĩ rằng điểm là Java 7 cho phép chuỗi không trả lại điều này, do đó thay đổi ngữ nghĩa của một cuộc gọi phương thức. – OregonGhost

Trả lời

12

các với tuyên bố có thể được dịch trong Java sử dụng các lớp nặc danh với initializer:

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

các nhược điểm của việc sử dụng thành ngữ này cũng là tài liệu here.

Yêu cầu ghép chuỗi là bí danh cho chuỗi phương pháp. Đó là nổi tiếng thành ngữ và làm việc với bất kỳ phiên bản của Java:

class Chained { 

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

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

một đề nghị cho JDK 7 là allowing of chaining method also for void return type:

class ChainedJava7 { 

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

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

Tôi vừa viết về khởi động đôi khi câu trả lời của bạn xuất hiện :-) –

+1

Điều này thực sự tốt đẹp. +1 –

+2

Lưu ý, thời hạn thay đổi ngôn ngữ nhỏ đối với JDK7 đã trôi qua vài tháng trước. –

1

Tôi không phải là người hâm mộ sử dụng này with; Tôi thích số Python with statement. Tuy nhiên, tôi đồng ý với bạn rằng void có nghĩa là void. Trong ví dụ bạn cung cấp, nếu một người thực sự muốn có khả năng tạo chuỗi các lời gọi phương thức, họ chỉ nên thay đổi kiểu trả về trên các phương thức của chúng để chúng có thể có chuỗi.

+0

Um, nó không có giá trị. Là một nhà sản xuất bạn không quan tâm để trả lại bất cứ điều gì, và người tiêu dùng của bạn không quan tâm để nhận được bất cứ điều gì (mặc dù đôi khi họ làm). Tại sao bạn cần quan tâm? Về mặt ngữ nghĩa, không có gì thay đổi (ngoại trừ việc phải nhập quá nhiều). –

+0

Ngoại trừ bạn * đang * trả lại một cái gì đó, và bạn đang làm nó ngầm. Nếu bạn không quay trở lại bất cứ điều gì, sau đó bạn không thể gọi một phương pháp trên đó. Vì đây là Java và khá nhiều mọi thứ khác là rõ ràng, tôi muốn trả về là rõ ràng. –

2

This có thể bạn quan tâm.

2

tôi khá giống như with báo cáo của hình thức đó nhưng tôi thích phiên bản VB của họ:

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

Khi mỗi thuộc tính trong khối With vẫn phải được đi trước bởi một . bạn biết rằng you'r e tham chiếu một thuộc tính đối tượng và không, nói, một biến cục bộ, giảm bất kỳ xung đột vùng tên nào.

Nếu chúng ta lấy ví dụ của bạn:

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

không có cách nào dễ dàng để nói nếu withSalt() là một phương pháp DrinkBuilder hoặc một phương pháp trong lớp địa phương. Nếu bạn chỉ cho phép các phương thức của đối tượng with -ed trong khối with thì tôi nghĩ chúng trở nên ít hữu ích hơn nhiều.

+0

Đề xuất của tôi sẽ là withSalt() sẽ là một phương thức của Trình tạo đồ uống. Nếu bạn thấy ứng dụng không làm những gì cần, bạn có thể gọi this.withSalt(); để làm cho nó rõ ràng phương thức withSalt() của đối tượng nên được gọi ra. –

1

Có thể nhiều cuộc gọi đến một đối tượng là dấu hiệu cho thấy một số mã cần được di chuyển xung quanh?

+2

Không, đây là một phần của toàn bộ câu thần chú Bean của Do One Thing vì Java không có thuộc tính hạng nhất, vì vậy chúng ta phải viết getters và setters cho mọi thứ. Đó là lý do tại sao. Một thứ khác đã bị loại bỏ khỏi Java 7 (thuộc tính). –

+0

@darthcoder - vui vì bạn đã đề cập đến điều đó! Tôi không thể hiểu tại sao điều này không phải là một phần của Java kể từ 1.0 –

1

Joshua Bloch trong Effective Java MụC# 2 khuyên bạn nên sử dụng Trình tạo khi bạn có một hàm tạo với nhiều đối số. Một lý do là nó có thể được viết để đảm bảo rằng đối tượng được xây dựng luôn ở trạng thái nhất quán. Nó cũng tránh có các "nhà xây dựng lồng ghép" phức tạp trong lớp của đối tượng được xây dựng. Một thứ khác nữa là nếu bạn muốn đối tượng dựng sẵn không thay đổi (ví dụ, đối với an toàn luồng), nó không thể có các phương thức setter.