设计:Java并在setter方法中返回自引用

时间:2022-04-09 11:26:24

For classes that have a long list of setters that are used frequently, I found this way very useful (although I have recently read about the Builder pattern in Effective Java that is kinda the same).

对于具有经常使用的长列表的类的类,我发现这种方式非常有用(尽管我最近读过有效Java中的Builder模式有点相同)。

Basically, all setter methods return the object itself so then you can use code like this:

基本上,所有setter方法都返回对象本身,因此您可以使用如下代码:

MyClass
    .setInt(1)
    .setString("test")
    .setBoolean(true);

Setters simply return this in the end:

塞特斯最终只是将其归还:

public MyClass setInt(int anInt) {
    // [snip]
    return this;
}

What is your opinion? What are the pros and cons? Does this have any impact on performance?

你有什么意见?优缺点都有什么?这对性能有影响吗?

11 个解决方案

#1


14  

@pek
Chained invocation is one of proposals for Java 7. It says that if a method return type is void, it should implicitly return this. If you're interested in this topic, there is a bunch of links and a simple example on Alex Miller's Java 7 page.

@pek链接调用是Java 7的提议之一。它说如果方法返回类型为void,它应该隐式返回它。如果你对这个主题感兴趣,那么在Alex Miller的Java 7页面上有一堆链接和一个简单的例子。

#2


9  

This is called a Fluent Interface, for reference.

这称为Fluent界面,供参考。

Personally, I think it's a pretty neat idea, but a matter of taste really. I think jQuery works this way.

就个人而言,我认为这是一个非常巧妙的想法,但真的是品味问题。我认为jQuery以这种方式工作。

#3


2  

I wouldn't do it myself, because to me it muddies what a particular method does, and the method-chaining is of limited use to me over doing it longhand. It isn't going to send me into a quivering ball of rage and psychosis, though, which is always a good thing. :')

我不会自己这样做,因为对我而言,特定方法所做的事情是混乱的,并且方法链对于我来说是有限的用法。然而,它不会让我陷入愤怒和精神病的颤抖之中,这总是一件好事。 :')

I wouldn't be concerned about performance; just ask Knuth.

我不会担心表现;请问Knuth。

#4


2  

It makes sense for builders, where all you are going to do is set a load of stuff, create the real object and throw the builder away. For builders, you might as well get rid of the "set" part of the method name. Similarly, immutable types don't really need the "get".

这对于构建者来说是有意义的,你要做的就是设置一堆东西,创建真实的对象并抛弃构建器。对于构建器,您也可以去掉方法名称的“set”部分。同样,不可变类型实际上并不需要“获取”。

Something thing = new SomethingBuilder()
    .aProperty(wotsit)
    .anotherProperty(somethingElse)
    .create();

A useful trick (if you don't mind a ~2K runtime overhead per class) is to use the double brace idiom:

一个有用的技巧(如果你不介意每个类的~2K运行时开销)是使用双括号成语:

JFrame frame = new JFrame("My frame") {{
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setLocation(frameTopLeft);
    add(createContents());
    pack();
    setVisible(true);
}};

#5


1  

I find this to be in poor style when used in setters. Immutable classes are usually a better fit for chaining, such as:

我发现这在用于制定者时风格很差。不可变类通常更适合链接,例如:

aWithB = myObject.withA(someA).withB(someB);

where myObject is of this class:

myObject属于这个类的位置:

class MyClass {
    withA(TypeA a) {
         this.a.equals(a) ? this : new MyClass(this, a);
    }

    private MyClass(MyClass copy, TypeA a) {
        this(copy);
        this.a = a;
    }
}

The builder pattern is also useful, since it allows the final object to be immutable while preventing the intermediate instances you would normally have to create when using this technique.

构建器模式也很有用,因为它允许最终对象不可变,同时防止在使用此技术时通常必须创建的中间实例。

#6


0  

This idea is seen a lot in c++, it allows operations to be cascaded...

这个想法在c ++中看得很多,它允许操作级联...

for example


std::cout << "this" << "is" << "cascading" 

is where the stream method << returns an instance of itself (*this).

stream方法< <返回自身的实例(* this)。< p>

see this: http://www.java2s.com/Tutorial/Cpp/0180__Class/Cascadingmemberfunctioncallswiththethispointer.htm

看到这个:http://www.java2s.com/Tutorial/Cpp/0180__Class/Cascadingmemberfunctioncallswiththethepointer.htm

#7


0  

I use to be a fan of the Java (and worse C#) practice of making getters and setters (get set properties) throughout an object. This use to be what I considered object oriented, but really this leads us just to exposing the guts and implementation of the object and not really taking advantage of encapsulation. There are times you can't get away from this (OR/M comes to mind), but in general the object should be set up and then perform its function. My dream objects tend to have one or two constructors, and maybe a half dozen functions that do work.

我习惯于成为Java(以及更糟糕的C#)在整个对象中制作getter和setter(获取set属性)的实践。这个用法是我认为面向对象的,但实际上这导致我们暴露对象的内核和实现而不是真正利用封装。有些时候你无法摆脱这种情况(OR / M浮现在脑海中),但一般来说,应该设置对象然后执行其功能。我的梦想对象往往有一两个构造函数,也许有六个函数可以工作。

The reason for this is that once I started developing API's there is a real need to keep things simple. You really only want to add as much complexity as is required to get the job done, and getters and setters, while simple in themselves, add complexity in heaps when added in mass. What happens when I load setters i na different order? Anythign different? Are you sure?

这样做的原因是,一旦我开始开发API,就需要保持简单。你真的只想添加完成工作所需的复杂性,以及getter和setter,虽然它们本身很简单,但是当大量添加时会增加堆的复杂性。当我按照不同的顺序加载setter时会发生什么? Anythign有什么不同?你确定吗?

#8


0  

@Dan again, for more complex situations (immutability comes in mind) the Builder Pattern is a great solution.

@Dan再次,对于更复杂的情况(不可变性),Builder Pattern是一个很好的解决方案。

Also, I agree with you mostly in getters. I believe what you are saying is to mostly follow the "Tell don't ask" paradigm and I greatly agree. But that is oriented mostly at getters.

另外,我主要是在吸气者中同意你的看法。我相信你所说的主要是遵循“不要问”的范式,我非常同意。但这主要是针对吸气剂。

Lastly, all of the above are for classes that have a great deal of attributes. I don't see a reason for any if you only have less than, say, 7.

最后,以上所有内容都适用于具有大量属性的类。如果你只有7比7,那我就没有理由。

#9


0  

I ended up doing this a lot when working with the Apache POI excel library; I ended up writing helper methods that chained so I could apply formatting, data types, internal cell data, formulas, and cell positioning.

在使用Apache POI excel库时,我最终做了很多事情。我最终编写了链接的辅助方法,因此我可以应用格式,数据类型,内部单元格数据,公式和单元格定位。

For stuff with lots of little tiny flyweight elements that need to have finicky little tweaks applied it works pretty well.

对于有很多微小飞重元素的东西,需要应用挑剔的小调整,它的效果非常好。

#10


0  

How To Use

如何使用

/**
 *
 * @author sanjay
 */
public class NewClass {
private int left ;
private int top;
public void set(int x,int y)
    {
    left=x;
    top=y;
}
public NewClass UP(int x)
    {
    top+=x;
    return this;
}
public NewClass DOWN(int x)
    {
    top-=x;
    return this;
}
public NewClass RIGHT(int x)
    {
    left+=x;
    return this;
}
public NewClass LEFT(int x)
    {
    left-=x;
    return this;
}
public void Display()
    {
    System.out.println("TOP:"+top);
    System.out.println("\nLEFT\n:"+left);
}
}
public static void main(String[] args) {
    // TODO code application logic here
    NewClass test = new NewClass();
    test.set(0,0);
    test.Display();
    test.UP(20).UP(45).DOWN(12).RIGHT(32).LEFT(20);
     test.Display();

#11


-2  

I agree with @Bernard that method chaining like this muddles the purpose of the setters. Instead I would suggest that if you are always creating chains of setters like this that you create a custom Constructor for your class so instead of

我同意@Bernard这样的链接方式会影响制定者的目的。相反,我建议如果你总是创建这样的setter链,你可以为你的类创建一个自定义的构造函数,而不是

    MyClass
    .setInt(1)
    .setString("test")
    .setBoolean(true)
  ;

You do

new MyClass(1,"test",true);

This makes it more readable and you can use this to make your class immutable if you chose to.

这使它更具可读性,如果您选择,可以使用它来使您的类不可变。

#1


14  

@pek
Chained invocation is one of proposals for Java 7. It says that if a method return type is void, it should implicitly return this. If you're interested in this topic, there is a bunch of links and a simple example on Alex Miller's Java 7 page.

@pek链接调用是Java 7的提议之一。它说如果方法返回类型为void,它应该隐式返回它。如果你对这个主题感兴趣,那么在Alex Miller的Java 7页面上有一堆链接和一个简单的例子。

#2


9  

This is called a Fluent Interface, for reference.

这称为Fluent界面,供参考。

Personally, I think it's a pretty neat idea, but a matter of taste really. I think jQuery works this way.

就个人而言,我认为这是一个非常巧妙的想法,但真的是品味问题。我认为jQuery以这种方式工作。

#3


2  

I wouldn't do it myself, because to me it muddies what a particular method does, and the method-chaining is of limited use to me over doing it longhand. It isn't going to send me into a quivering ball of rage and psychosis, though, which is always a good thing. :')

我不会自己这样做,因为对我而言,特定方法所做的事情是混乱的,并且方法链对于我来说是有限的用法。然而,它不会让我陷入愤怒和精神病的颤抖之中,这总是一件好事。 :')

I wouldn't be concerned about performance; just ask Knuth.

我不会担心表现;请问Knuth。

#4


2  

It makes sense for builders, where all you are going to do is set a load of stuff, create the real object and throw the builder away. For builders, you might as well get rid of the "set" part of the method name. Similarly, immutable types don't really need the "get".

这对于构建者来说是有意义的,你要做的就是设置一堆东西,创建真实的对象并抛弃构建器。对于构建器,您也可以去掉方法名称的“set”部分。同样,不可变类型实际上并不需要“获取”。

Something thing = new SomethingBuilder()
    .aProperty(wotsit)
    .anotherProperty(somethingElse)
    .create();

A useful trick (if you don't mind a ~2K runtime overhead per class) is to use the double brace idiom:

一个有用的技巧(如果你不介意每个类的~2K运行时开销)是使用双括号成语:

JFrame frame = new JFrame("My frame") {{
    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    setLocation(frameTopLeft);
    add(createContents());
    pack();
    setVisible(true);
}};

#5


1  

I find this to be in poor style when used in setters. Immutable classes are usually a better fit for chaining, such as:

我发现这在用于制定者时风格很差。不可变类通常更适合链接,例如:

aWithB = myObject.withA(someA).withB(someB);

where myObject is of this class:

myObject属于这个类的位置:

class MyClass {
    withA(TypeA a) {
         this.a.equals(a) ? this : new MyClass(this, a);
    }

    private MyClass(MyClass copy, TypeA a) {
        this(copy);
        this.a = a;
    }
}

The builder pattern is also useful, since it allows the final object to be immutable while preventing the intermediate instances you would normally have to create when using this technique.

构建器模式也很有用,因为它允许最终对象不可变,同时防止在使用此技术时通常必须创建的中间实例。

#6


0  

This idea is seen a lot in c++, it allows operations to be cascaded...

这个想法在c ++中看得很多,它允许操作级联...

for example


std::cout << "this" << "is" << "cascading" 

is where the stream method << returns an instance of itself (*this).

stream方法< <返回自身的实例(* this)。< p>

see this: http://www.java2s.com/Tutorial/Cpp/0180__Class/Cascadingmemberfunctioncallswiththethispointer.htm

看到这个:http://www.java2s.com/Tutorial/Cpp/0180__Class/Cascadingmemberfunctioncallswiththethepointer.htm

#7


0  

I use to be a fan of the Java (and worse C#) practice of making getters and setters (get set properties) throughout an object. This use to be what I considered object oriented, but really this leads us just to exposing the guts and implementation of the object and not really taking advantage of encapsulation. There are times you can't get away from this (OR/M comes to mind), but in general the object should be set up and then perform its function. My dream objects tend to have one or two constructors, and maybe a half dozen functions that do work.

我习惯于成为Java(以及更糟糕的C#)在整个对象中制作getter和setter(获取set属性)的实践。这个用法是我认为面向对象的,但实际上这导致我们暴露对象的内核和实现而不是真正利用封装。有些时候你无法摆脱这种情况(OR / M浮现在脑海中),但一般来说,应该设置对象然后执行其功能。我的梦想对象往往有一两个构造函数,也许有六个函数可以工作。

The reason for this is that once I started developing API's there is a real need to keep things simple. You really only want to add as much complexity as is required to get the job done, and getters and setters, while simple in themselves, add complexity in heaps when added in mass. What happens when I load setters i na different order? Anythign different? Are you sure?

这样做的原因是,一旦我开始开发API,就需要保持简单。你真的只想添加完成工作所需的复杂性,以及getter和setter,虽然它们本身很简单,但是当大量添加时会增加堆的复杂性。当我按照不同的顺序加载setter时会发生什么? Anythign有什么不同?你确定吗?

#8


0  

@Dan again, for more complex situations (immutability comes in mind) the Builder Pattern is a great solution.

@Dan再次,对于更复杂的情况(不可变性),Builder Pattern是一个很好的解决方案。

Also, I agree with you mostly in getters. I believe what you are saying is to mostly follow the "Tell don't ask" paradigm and I greatly agree. But that is oriented mostly at getters.

另外,我主要是在吸气者中同意你的看法。我相信你所说的主要是遵循“不要问”的范式,我非常同意。但这主要是针对吸气剂。

Lastly, all of the above are for classes that have a great deal of attributes. I don't see a reason for any if you only have less than, say, 7.

最后,以上所有内容都适用于具有大量属性的类。如果你只有7比7,那我就没有理由。

#9


0  

I ended up doing this a lot when working with the Apache POI excel library; I ended up writing helper methods that chained so I could apply formatting, data types, internal cell data, formulas, and cell positioning.

在使用Apache POI excel库时,我最终做了很多事情。我最终编写了链接的辅助方法,因此我可以应用格式,数据类型,内部单元格数据,公式和单元格定位。

For stuff with lots of little tiny flyweight elements that need to have finicky little tweaks applied it works pretty well.

对于有很多微小飞重元素的东西,需要应用挑剔的小调整,它的效果非常好。

#10


0  

How To Use

如何使用

/**
 *
 * @author sanjay
 */
public class NewClass {
private int left ;
private int top;
public void set(int x,int y)
    {
    left=x;
    top=y;
}
public NewClass UP(int x)
    {
    top+=x;
    return this;
}
public NewClass DOWN(int x)
    {
    top-=x;
    return this;
}
public NewClass RIGHT(int x)
    {
    left+=x;
    return this;
}
public NewClass LEFT(int x)
    {
    left-=x;
    return this;
}
public void Display()
    {
    System.out.println("TOP:"+top);
    System.out.println("\nLEFT\n:"+left);
}
}
public static void main(String[] args) {
    // TODO code application logic here
    NewClass test = new NewClass();
    test.set(0,0);
    test.Display();
    test.UP(20).UP(45).DOWN(12).RIGHT(32).LEFT(20);
     test.Display();

#11


-2  

I agree with @Bernard that method chaining like this muddles the purpose of the setters. Instead I would suggest that if you are always creating chains of setters like this that you create a custom Constructor for your class so instead of

我同意@Bernard这样的链接方式会影响制定者的目的。相反,我建议如果你总是创建这样的setter链,你可以为你的类创建一个自定义的构造函数,而不是

    MyClass
    .setInt(1)
    .setString("test")
    .setBoolean(true)
  ;

You do

new MyClass(1,"test",true);

This makes it more readable and you can use this to make your class immutable if you chose to.

这使它更具可读性,如果您选择,可以使用它来使您的类不可变。