kotlin 中数据 class 的流畅方法
Fluent methods for data class in kotlin
我们熟悉在 java 和其他编程语言中调用方法的流畅接口。例如:
Picasso.with(this).load(url).into(imageView);
这可以通过 setter 方法实现 return 所需类型的对象。
public Picasso with(Context context)
{
this.context = context;
return this;
}
public X load(String url)
{
this.url = url;
return this;
}
public Y load(ImageView imageView)
{
this.imageView = imageView;
return this;
}
我正在尝试对 kotlin 数据做同样的事情 类 但遗憾的是我找不到一种方法来覆盖我在其中使用的 setter 方法可以 return 该对象的新实例。
当我尝试强行覆盖 setter 方法时出现编译器错误。
关于可以做什么的任何想法,以便我可以调用流畅的接口或至少改变 setter 的工作方式
可能是这样的
data class CorruptOfficeAccount(.....){
override fun addCollectedFee(Long money) :CorruptOfficeAccount {
this.money = money/5
}
}
这样我就可以打电话给
CorrutOfficeAccount(....).method1().addCollectedFee(20000).method3()
如果除了 Name
之外不需要 return 任何东西,您可以这样做:
data class Name(var firstName: String, var lastName: String)
fun foo() {
val name = ...
name.apply {
firstName = ...
lastName = ...
}
}
或另一个例子:
CorrutOfficeAccount(....).apply {
method1()
addCollectedFee(20000)
method3()
}
传递给apply
的函数内部(花括号里面的东西),this
是对象apply
被调用,这使得可以引用成员函数和firstName
之类的属性而不写 name.firstName
.
如果您对此不满意:不可能制作实际的 setter return 东西,但是您当然可以定义一个具有不同名称的方法并制作 return 东西.
为了在 Kotlin 中访问属性,我们不使用 getter 和 setter 函数,虽然您可以重写它们的 setter 以赋予它们自定义行为,但您可以不要让它们 return 任何东西,因为调用它们是一个赋值,这不是 Kotlin 中的表达式。例如,这不起作用:
var x = 1
var y = (x = 5) // "Assigments are not expressions, and only expressions are allowed in this context"
您可以做的是定义设置它们的其他方法,然后 return 调用它们的实例。例如:
data class Name(var firstName: String = "", var lastName: String = "") {
fun withLastName(lastName: String): Name {
this.lastName = lastName
return this
}
}
val name = Name(firstName = "Jane")
name.withLastName("Doe").withLastName("Carter")
请注意,如果您将此方法命名为 setLastName
,那么在使用 Java 中的 class 时会遇到问题,因为 lastName
属性当您编写 Java 代码时,通过名为 setLastName
的方法已经可见。
虽然在 Kotlin 中更常见的解决方案是使用标准库中的 apply
替换流畅的构建器,正如 Christian 的回答中所描述的那样。
感谢 Zsmb13 和 Christin 的回答,但如果有人想使用不可变字段,我有另一个解决方案
data class Foo(val fooString: String = "", val fooInt: Int = 0) {
fun increaseTwo() = copy(fooInt = fooInt + 2)
fun increaseThree() = copy(fooInt = fooInt + 3)
}
你可以像这样使用它
println( Foo("foo",2).increaseTwo().increaseThree())
输出:
Foo(fooString=foo, fooInt=7)
我们熟悉在 java 和其他编程语言中调用方法的流畅接口。例如:
Picasso.with(this).load(url).into(imageView);
这可以通过 setter 方法实现 return 所需类型的对象。
public Picasso with(Context context)
{
this.context = context;
return this;
}
public X load(String url)
{
this.url = url;
return this;
}
public Y load(ImageView imageView)
{
this.imageView = imageView;
return this;
}
我正在尝试对 kotlin 数据做同样的事情 类 但遗憾的是我找不到一种方法来覆盖我在其中使用的 setter 方法可以 return 该对象的新实例。
当我尝试强行覆盖 setter 方法时出现编译器错误。
关于可以做什么的任何想法,以便我可以调用流畅的接口或至少改变 setter 的工作方式 可能是这样的
data class CorruptOfficeAccount(.....){
override fun addCollectedFee(Long money) :CorruptOfficeAccount {
this.money = money/5
}
}
这样我就可以打电话给
CorrutOfficeAccount(....).method1().addCollectedFee(20000).method3()
如果除了 Name
之外不需要 return 任何东西,您可以这样做:
data class Name(var firstName: String, var lastName: String)
fun foo() {
val name = ...
name.apply {
firstName = ...
lastName = ...
}
}
或另一个例子:
CorrutOfficeAccount(....).apply {
method1()
addCollectedFee(20000)
method3()
}
传递给apply
的函数内部(花括号里面的东西),this
是对象apply
被调用,这使得可以引用成员函数和firstName
之类的属性而不写 name.firstName
.
如果您对此不满意:不可能制作实际的 setter return 东西,但是您当然可以定义一个具有不同名称的方法并制作 return 东西.
为了在 Kotlin 中访问属性,我们不使用 getter 和 setter 函数,虽然您可以重写它们的 setter 以赋予它们自定义行为,但您可以不要让它们 return 任何东西,因为调用它们是一个赋值,这不是 Kotlin 中的表达式。例如,这不起作用:
var x = 1
var y = (x = 5) // "Assigments are not expressions, and only expressions are allowed in this context"
您可以做的是定义设置它们的其他方法,然后 return 调用它们的实例。例如:
data class Name(var firstName: String = "", var lastName: String = "") {
fun withLastName(lastName: String): Name {
this.lastName = lastName
return this
}
}
val name = Name(firstName = "Jane")
name.withLastName("Doe").withLastName("Carter")
请注意,如果您将此方法命名为 setLastName
,那么在使用 Java 中的 class 时会遇到问题,因为 lastName
属性当您编写 Java 代码时,通过名为 setLastName
的方法已经可见。
虽然在 Kotlin 中更常见的解决方案是使用标准库中的 apply
替换流畅的构建器,正如 Christian 的回答中所描述的那样。
感谢 Zsmb13 和 Christin 的回答,但如果有人想使用不可变字段,我有另一个解决方案
data class Foo(val fooString: String = "", val fooInt: Int = 0) {
fun increaseTwo() = copy(fooInt = fooInt + 2)
fun increaseThree() = copy(fooInt = fooInt + 3)
}
你可以像这样使用它
println( Foo("foo",2).increaseTwo().increaseThree())
输出:
Foo(fooString=foo, fooInt=7)