繁体   English   中英

如何定义方法返回的结构类型

[英]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的结构类型,如何才能自行返回生成器?

type StructurallyBuilder = {
    def setA(xxx): StructurallyBuilder
    def setB(yyy): StructurallyBuilder
}

当我要在StructurallyBuilder上使用setA和setB时,编译器会抱怨它无法解析。

这并非一帆风顺,但我相信您可以使用F界多态来实现:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM