如何定义方法 return this 的结构类型
How define Structural Type that the method return this
我有一些 Builder
来自库,源代码是在 Java 中自动生成的,超出了我的控制范围。这些 Builder
彼此之间没有关系,但它们有许多结构完全相同的方法。
package a.b
public class Builder {
public Builder setA(xxx) {}
public Builder setB(yyy) {}
}
package a.c
public class Builder {
public Builder setA(xxx) {}
public Builder setB(yyy) {}
}
使用 Scala 的结构类型,我如何 return 自己的构建器?
type StructurallyBuilder = {
def setA(xxx): StructurallyBuilder
def setB(yyy): StructurallyBuilder
}
当我想在 StructurallyBuilder
上使用 setA 和 setB 时,编译器抱怨它无法解析。
这不是很简单,但我相信您可以使用 F-bounded polymorphism 来实现:
type StructurallyBuilder[F <: StructurallyBuilder[F]] = {
def setA(xxx: Int): F
def setB(yyy: Int): F
}
在定义 类 或使用这些构建器的方法时,您必须保留这个复杂的签名。例如:
def setA[T <: StructurallyBuilder[T]](
xxx: Int,
builder: StructurallyBuilder[T]
): T = builder.setA(xxx)
不过看来你可以正常使用那些方法:
val bld: a.c.Builder = setA(10, new a.c.Builder())
您可以将实际构建器设为结构类型的类型参数:
import scala.language.reflectiveCalls
import scala.language.existentials
type StructurallyBuilder[T <: AnyRef] = AnyRef {
def setA(xxx): T
def setB(yyy): T
}
这是我写的一个小测试,用于证明您可以使用它来传递任何使用 'StructurallyBuilder' 作为参数类型的构建器:
import scala.language.reflectiveCalls
import scala.language.existentials
type StructurallyBuilder[T <: AnyRef] = AnyRef {
def setA(a: Int): T
def setB(b: String): T
}
class Builder1 {
var a: Int = _
var b: String = _
def setA(a: Int): Builder1 = {
this.a = a
this
}
def setB(b: String): Builder1 = {
this.b = b
this
}
}
val builder: StructurallyBuilder[_] = new Builder1
val b2 = builder.setA(1)
val b3 = builder.setB("B")
val builder2 = new Builder1
def test(builder: StructurallyBuilder[_]): String = {
builder.toString
}
val t2 = test(builder2) |-> t2: String = Builder1@7a067558
为什么不使用 this.type?
type StructurallyBuilder = {
def setA(x: Int): this.type
def setB(y: Double): this.type
}
这种用法的例子:
object App
{
class A {
def setA(x: Int): this.type = { this }
def setB(y: Double): this.type = { this }
}
type StructurallyBuilder = {
def setA(x: Int): this.type
def setB(y: Double): this.type
}
def main(args: Array[String]):Unit =
{
val a = new A()
if (a.isInstanceOf[StructurallyBuilder]) {
System.out.println("qqq")
}
System.out.println(a)
}
}
然后,尝试 运行:
[info] Running X.App
qqq
X.App$A@8f59676
我有一些 Builder
来自库,源代码是在 Java 中自动生成的,超出了我的控制范围。这些 Builder
彼此之间没有关系,但它们有许多结构完全相同的方法。
package a.b
public class Builder {
public Builder setA(xxx) {}
public Builder setB(yyy) {}
}
package a.c
public class Builder {
public Builder setA(xxx) {}
public Builder setB(yyy) {}
}
使用 Scala 的结构类型,我如何 return 自己的构建器?
type StructurallyBuilder = {
def setA(xxx): StructurallyBuilder
def setB(yyy): StructurallyBuilder
}
当我想在 StructurallyBuilder
上使用 setA 和 setB 时,编译器抱怨它无法解析。
这不是很简单,但我相信您可以使用 F-bounded polymorphism 来实现:
type StructurallyBuilder[F <: StructurallyBuilder[F]] = {
def setA(xxx: Int): F
def setB(yyy: Int): F
}
在定义 类 或使用这些构建器的方法时,您必须保留这个复杂的签名。例如:
def setA[T <: StructurallyBuilder[T]](
xxx: Int,
builder: StructurallyBuilder[T]
): T = builder.setA(xxx)
不过看来你可以正常使用那些方法:
val bld: a.c.Builder = setA(10, new a.c.Builder())
您可以将实际构建器设为结构类型的类型参数:
import scala.language.reflectiveCalls
import scala.language.existentials
type StructurallyBuilder[T <: AnyRef] = AnyRef {
def setA(xxx): T
def setB(yyy): T
}
这是我写的一个小测试,用于证明您可以使用它来传递任何使用 'StructurallyBuilder' 作为参数类型的构建器:
import scala.language.reflectiveCalls
import scala.language.existentials
type StructurallyBuilder[T <: AnyRef] = AnyRef {
def setA(a: Int): T
def setB(b: String): T
}
class Builder1 {
var a: Int = _
var b: String = _
def setA(a: Int): Builder1 = {
this.a = a
this
}
def setB(b: String): Builder1 = {
this.b = b
this
}
}
val builder: StructurallyBuilder[_] = new Builder1
val b2 = builder.setA(1)
val b3 = builder.setB("B")
val builder2 = new Builder1
def test(builder: StructurallyBuilder[_]): String = {
builder.toString
}
val t2 = test(builder2) |-> t2: String = Builder1@7a067558
为什么不使用 this.type?
type StructurallyBuilder = {
def setA(x: Int): this.type
def setB(y: Double): this.type
}
这种用法的例子:
object App
{
class A {
def setA(x: Int): this.type = { this }
def setB(y: Double): this.type = { this }
}
type StructurallyBuilder = {
def setA(x: Int): this.type
def setB(y: Double): this.type
}
def main(args: Array[String]):Unit =
{
val a = new A()
if (a.isInstanceOf[StructurallyBuilder]) {
System.out.println("qqq")
}
System.out.println(a)
}
}
然后,尝试 运行:
[info] Running X.App
qqq
X.App$A@8f59676