Java:不可变类的伪设置器方法 [英] Java: pseudo-setter method for immutable classes

查看:50
本文介绍了Java:不可变类的伪设置器方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我在Java中有一个Foo类,它具有不可变的数据:

Let's say I have a class Foo in Java that has immutable data:

class Foo {
    final private int x;
    public int getX() { return this.x; }
    final private OtherStuff otherstuff;
    public Foo(int x, OtherStuff otherstuff) { 
       this.x = x;
       this.otherstuff = otherstuff;
    }   
    // lots of other stuff...
}

现在,我想添加一个实用程序方法,该方法创建状态相同但具有新值x的同级"值.我可以称它为setX():

Now I'd like to add a utility method that creates a "sibling" value with identical state but with a new value of x. I could call it setX():

class Foo
{
    ...
    Foo setX(int newX) { return new Foo(newX, this.otherstuff); }
    ...
}

但是setX()的语义与可变bean对象的标准setter约定不同,因此某种程度上感觉不对.

but the semantics of setX() are different than the standard setter convention for mutable bean objects, so somehow this doesn't feel right.

此方法的最佳名称是什么?

What's the best name for this method?

我应该叫它withX()还是newX()或其他名称吗?

Should I call it withX() or newX() or something else?

edit:在我的情况下,还需要优先考虑:我有脚本客户端(通过JSR-223和导出的对象模型)可以轻松获得Foo对象.但是,调用构造函数或创建构建器或其他方法很麻烦.因此,我希望提供这种方法来方便编写客户端脚本.

edit: additional priority in my case: I have scripting clients (through JSR-223 and an object model I export) that can easily obtain a Foo object. It's cumbersome, however, to call constructors or create builders or whatever. So it's desirable for me to provide this method as a convenience for scripting clients.

推荐答案

原创文章:不可变的设置器:命名约定(来自Programming.Guide)

Original article: Immutable Setters: Naming Conventions (from Programming.Guide)

这是不可变设置器的事实上的标准命名约定.例如,这是 Immutables 框架生成的设置器的默认名称.这是一个示例:

This is the de facto standard naming convention for immutable setters. This is for example the default name for setters generated by the Immutables framework. Here's an example:

Foo newFoo = foo.withX(1047);

有一个@Value.Style选项可以更改此模式,但是该选项本身称为with="...",它强调了默认约定.

There is a @Value.Style option to change this pattern, but the option itself is called with="...", which emphasizes what the default convention is.

作为最广泛的约定,很容易找到这样的例子. 番石榴和Java

Being the most widespread convention, it's easy to find examples of this. Guava and the Java time package being two.

另一种方法是根本没有前缀.例如,您可以在 Immutables 框架生成的构建器中看到这一点:

Another approach is to not have a prefix at all. You see this in for example builders generated by the Immutables framework:

Foo foo = ImmutableFoo.builder()
                      .x(1047)
                      .y("Hello World")
                      .build();

如果直接在不可变的类上使用此方法(即不涉及任何构建器),通常会将其作为getter的重载:

If you use this approach directly on the immutable class (that is, no builder involved) you'd typically have it as an overload to the getter:

Foo newFoo = foo.x(5);  // setter - one argument
int x = newFoo.x();     // getter - no arguments

例如, Java Spark 框架中使用了该约定.

This convention is used in for example the Java Spark framework.

某些API使用与可变类中的setter相同的命名约定.这有一个明显的缺点,那就是当您刚接触代码库时可能会感到惊讶.使用 BigInteger 并编写…

Some APIs use the same naming convention as for setters in mutable classes. This has the obvious drawback that it can be surprising when you're new to a code base. Working with BigInteger and writing…

bigInt.setBit(2);

…例如将是一个错误,因为返回的对象被丢弃了.使用这种命名模式,您必须习惯于写作

…would for example be a mistake, since the returned object is discarded. With this naming pattern you have to get used to writing

BigInteger newBigInt = bigInt.setBit(2);

deriveX(...)

要突出显示新值是从现有对象派生的事实,可以使用deriveX(...).不变的 Font 类Java API遵循此模式.如果要使用例如特定大小的字体创建新字体,请使用

deriveX(...)

To highlight the fact that the new value is derived from the existing object, you could use deriveX(...). The immutable Font class in the Java API follows this pattern. If you want to create a new font with, for example, a specific size you use

Font newFont = font.deriveFont(newSize);

Font类自开始以来就存在.到目前为止,这种约定并不十分普遍.

The Font class has been around since the beginning of time. This convention is not very common as of today.

当不可变对象本身是转换的操作数时,它实际上不是传统意义上的setter,因此不需要为该方法添加前缀.例如……

When the immutable object is itself an operand to the transformation it's not really a setter in the traditional sense, and there's no need to have a prefix for the method. For example…

BigDecimal newBigDec = bigDec.multiply(BigDecimal.TEN);

...具有与设置器相同的签名,但是multiply显然比其他任何替代方法都更好.

…has the same signature as a setter, but multiply is clearly a better method name than any other alternative.

String.substringPath.resolve等相同

这篇关于Java:不可变类的伪设置器方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆