Java 7 中的链式调用?

发布于 2024-07-25 11:03:13 字数 1444 浏览 10 评论 0原文

我刚刚阅读了 Java 7 预览演示文稿 (pdf),其中有一张幻灯片链式调用。 这是幻灯片中使用的示例:

// 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() 也不太方便。

现在,我从Delphi世界来到Java。 在Delphi中,有 with语言构造。 这是少数人所珍视的,而许多人所厌恶的(或者是相反?)。 我发现 with 比链式调用的想法更优雅(我相信它的工作原理是 void 方法返回对其调用的对象的引用 - 并且这是我不喜欢的部分,因为 void 应该返回什么都)。

我希望 Java 采用 with 语言功能,因此示例代码可以这样编写:

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

我是唯一一个更喜欢这种解决方案而不是链式调用的人吗? 还有人认为 with 可能是 Java 语言的有用扩展吗? (让我想起有人关于“Java ++”需求的问题......)

I was just reading a Java 7 preview presentation (pdf) and there was a slide on Chained Invocation. Here is the example used in the slide:

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

And I have mixed feelings about this. One shouldn't chain too many method invocations into one statement. On the other hand, writing margarita.this() and margarita.that() isn't too convenient either.

Now, I am coming to Java from Delphi world. And in Delphi there is the with language construct. This is cherished by a few and loathed by many (or is it the other way around?). I find with to be more elegant than the idea of chained invocation (which I believe works on the basis of void method returning reference to object on which it has been invoked - and this is the part I don't like, as void should return nothing).

I would appreciate the with language feature being adopted by Java, so the example code could be written like so:

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

Am I the only one who would prefer this solution to the chained invocation? Anyone else feels that with could be a useful extension to Java language? (Reminds me of someone's question about the need of "Java++"...)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

沫尐诺 2024-08-01 11:03:13

with 语句可以使用带有初始值设定项的匿名类在 Java 中进行翻译:

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

使用此习惯用法的缺点已有详细记录此处

链接调用是方法链接的别名。 这是众所周知的习惯用法,适用于任何版本的 Java:

class Chained {

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

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

JDK 7 的建议是允许链接方法也适用于 void 返回类型

class ChainedJava7 {

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

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

the with statement can be translated in Java using anonymous classes with initializer:

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

the downsides of using this idiom are well documented here.

Chained Invocation is an alias for Method Chaining. That is well known idiom and works with any version of Java:

class Chained {

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

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

a proposal for JDK 7 is allowing of chaining method also for void return type:

class ChainedJava7 {

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

    public void withBar() { 
        // ...
    }
}    
欲拥i 2024-08-01 11:03:13

您可能感兴趣。

This might interest you.

合久必婚 2024-08-01 11:03:13

我非常喜欢这种形式的 with 语句,但我更喜欢它们的 VB 版本:

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

因为 With 块中的每个属性仍然必须前面有一个 .< /code> 您知道您引用的是对象属性,而不是局部变量,从而减少了任何命名空间冲突。

如果我们以您的例子为例:

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

没有简单的方法来判断 withSalt()DrinkBuilder 的方法还是本地类中的方法。 如果您只允许在 with 块中使用 with-ed 对象的方法,那么我认为它们的用处会大大降低。

I quite like with statements of that form but I prefer the VB version of them:

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

As each attribute in the With block still has to be preceded by a . you know that you're referencing an Object property and not, say, a local variable, reducing any namespace collisions.

If we take your example:

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

there's no easy way to tell if withSalt() is a method of DrinkBuilder or a method in local class. If you only allow methods of the with-ed object in the with block then I think they become much less useful.

云朵有点甜 2024-08-01 11:03:13

我不喜欢使用 with; 我更喜欢 Python with 语句。 不过,我确实同意您的观点,void 应该意味着 void。 在您提供的示例中,如果一个人确实希望能够链接方法调用,他们应该只更改其方法的返回类型,以便它们可以链接。

I'm not a fan of this use of with; I much prefer the Python with statement. I do agree with you that void should mean void, though. In the example you provide, if a person really wants to be able to chain method invocations they should just change the return types on their methods so they're chainable.

眸中客 2024-08-01 11:03:13

也许对一个对象的多次调用是某些代码需要移动的标志?

Maybe the many many calls to one object are the sign that some code needs to be moved around?

你げ笑在眉眼 2024-08-01 11:03:13

Joshua Bloch 在 Effective Java 项目 #2 中强烈建议在以下情况下使用 Builder:有一个带有很多参数的构造函数。 原因之一是它可以被编写为保证构建的对象始终处于一致的状态。 它还避免了在构建对象的类中出现复杂的“伸缩构造函数”。 还有一个问题是,如果您希望构建的对象是不可变的(例如,为了线程安全),它就不能有 setter 方法。

Joshua Bloch in Effective Java Item #2 strongly recommends the use of a Builder when you have a constructor with a lot of arguments. One reason is that it can be written to guarantee that the built object is always in a consistent state. It also avoids having complex "telescoping constructors" in the built object's class. Still another is that if you want the built object to be immutable (eg, for thread safety), it can't have setter methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文