Scala - 使用动态字段复制大小写 class。可能吗?
Scala - copy case class with dynamic fields. Is it possible?
考虑到案例 class 在创建时计算了默认字段,是否可以在新复制的案例 class 重新计算该字段的地方复制它?
例如TestCopy.auto
在创建时生成:
case class TestCopy(static: String, auto: Long = System.currentTimeMillis()) {
val auto2 = System.currentTimeMillis()
}
如果我复制它只改变字段 static
:
val a = TestCopy(static = "a")
val b = a.copy(static = "b")
字段 auto
未重新计算。构造函数字段 auto2
:
也不是
> println(a)
> println(b)
> println(a.auto2)
> println(b.auto2)
TestCopy(a,1640773176392)
TestCopy(b,1640773176392)
1640773176392
1640773176392
其实是有道理的,因为我是抄案例class。 但是,我想要一种类似于重新创建案例 class 的行为,我只更改了一组静态字段。 上面的示例已经过简化,我本可以重新创建它.问题是针对这样的情况:
case class TestCopy2(static1: String,
static2: String,
static3: String,
auto: Long = System.currentTimeMillis())
这里只有static1
要改,static2
和static3
要复制,还要重新生成auto
。
可能吗?
谢谢大家
自定义 apply
方法是可行的,但您也应该能够利用 abstract case class
技巧:
abstract case class TestCopy(static: String, auto: Long = System.currentTimeMillis()) {
def copy(static: String = static, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
object TestCopy {
def apply(static: String, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
制作 case class
abstract
会抑制自动生成的 apply
和 copy
方法。在这种情况下,自动生成的 apply
基本上就是编译器生成的内容。生成的 copy
通常类似于
def copy(static: String = static, auto: Long = auto): TestCopy
请注意 auto
默认为以前的值,所以这是我们想要更改的行为,因此我们定义了一个自定义 copy
方法来替换编译器生成的方法。
可以通过将构造函数设为私有来消除 auto
的默认值之一;由于 case class
es 通常不使用 new
实例化,因此损失不大:
abstract case class TestCopy private (static: String, auto: Long) {
def copy(static: String = static, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
object TestCopy {
def apply(static: String, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
现在您可以:
- 使用默认当前时间创建:
TestCopy("foo")
- 使用预设时间创建:
TestCopy("foo", 0)
- 复制当前时间:
TestCopy("foo").copy(static = "bar")
- 复制预设时间:
TestCopy("foo").copy(auto = 0)
不会自动复制瞬态值:
case class Foo(a: Int) {
@transient val b: Long = System.currentTimeMillis
}
val f1 = Foo(1)
Thread.sleep(1000)
val f2 = f1.copy(2)
assert f1.b != f2.b
考虑到案例 class 在创建时计算了默认字段,是否可以在新复制的案例 class 重新计算该字段的地方复制它?
例如TestCopy.auto
在创建时生成:
case class TestCopy(static: String, auto: Long = System.currentTimeMillis()) {
val auto2 = System.currentTimeMillis()
}
如果我复制它只改变字段 static
:
val a = TestCopy(static = "a")
val b = a.copy(static = "b")
字段 auto
未重新计算。构造函数字段 auto2
:
> println(a)
> println(b)
> println(a.auto2)
> println(b.auto2)
TestCopy(a,1640773176392)
TestCopy(b,1640773176392)
1640773176392
1640773176392
其实是有道理的,因为我是抄案例class。 但是,我想要一种类似于重新创建案例 class 的行为,我只更改了一组静态字段。 上面的示例已经过简化,我本可以重新创建它.问题是针对这样的情况:
case class TestCopy2(static1: String,
static2: String,
static3: String,
auto: Long = System.currentTimeMillis())
这里只有static1
要改,static2
和static3
要复制,还要重新生成auto
。
可能吗?
谢谢大家
自定义 apply
方法是可行的,但您也应该能够利用 abstract case class
技巧:
abstract case class TestCopy(static: String, auto: Long = System.currentTimeMillis()) {
def copy(static: String = static, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
object TestCopy {
def apply(static: String, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
制作 case class
abstract
会抑制自动生成的 apply
和 copy
方法。在这种情况下,自动生成的 apply
基本上就是编译器生成的内容。生成的 copy
通常类似于
def copy(static: String = static, auto: Long = auto): TestCopy
请注意 auto
默认为以前的值,所以这是我们想要更改的行为,因此我们定义了一个自定义 copy
方法来替换编译器生成的方法。
可以通过将构造函数设为私有来消除 auto
的默认值之一;由于 case class
es 通常不使用 new
实例化,因此损失不大:
abstract case class TestCopy private (static: String, auto: Long) {
def copy(static: String = static, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
object TestCopy {
def apply(static: String, auto: Long = System.currentTimeMillis()): TestCopy =
new TestCopy(static, auto)
}
现在您可以:
- 使用默认当前时间创建:
TestCopy("foo")
- 使用预设时间创建:
TestCopy("foo", 0)
- 复制当前时间:
TestCopy("foo").copy(static = "bar")
- 复制预设时间:
TestCopy("foo").copy(auto = 0)
不会自动复制瞬态值:
case class Foo(a: Int) {
@transient val b: Long = System.currentTimeMillis
}
val f1 = Foo(1)
Thread.sleep(1000)
val f2 = f1.copy(2)
assert f1.b != f2.b