我有一个看起来像这样的课程:
class X[A <: Throwable, B, C](b: B, c: C)
可以推断出A,B和C,所以我可以用:
实例化它val x = new X(3, 4)
给了我一个X [Nothing,Int,Int] - 经常是我想要的。
但我有时想将A指定为Nothing以外的东西(比如说AssertionError)。如果没有指定B和C,这是可能的吗?我想象的语法如下:
val x = new X[AssertionError](3, 4)
val x = new X[AssertionError, _, _](3, 4)
val x = new X[AssertionError,,](3, 4)
但显然这不起作用。
是否有一些语法,或者我可以通过某种方式获得相同的结果?
答案 0 :(得分:5)
我主要担心的是在使用时使这很容易(我不想为每次使用定义新类型,因为异常类型通常不同)。我发现我可以使用伴侣对象来建造一个中间工厂:
class X[A <: Throwable, B, C](b: B, c: C) {
}
trait XFactory[A <: Throwable] {
def apply[B, C](b: B, c: C): X[A, B, C]
}
object X {
def apply[A <: Throwable: Manifest](): XFactory[A] = {
new XFactory[A] {
override def apply[B, C](b: B, c: C): X[A, B, C] = {
new X(b, c)
}
}
}
}
val x = X[AssertionError].apply(3,3)
我能看到的唯一缺点是你必须拼出“申请”。
答案 1 :(得分:3)
如果你不害怕简洁的硬核语法,你可能想要type lamdas使用它:
Welcome to Scala version 2.10.0-20121205-235900-18481cef9b (OpenJDK 64-Bit Server VM, Java 1.7.0_15).
Type in expressions to have them evaluated.
Type :help for more information.
scala> case class X[A <: Throwable, B, C](b: B, c: C)
defined class X
scala> type P[A,B] = ({type l[a,b] = X[AssertionError, a, b]})#l[A,B]
defined type alias P
scala> val x = new P(1,2)
x: X[AssertionError,Int,Int] = X(1,2)
尽管如此,正如Frank S. Thomas所建议的那样,定义类型别名是一种方法。
答案 2 :(得分:3)
您可以定义类型别名,其中第一个类型参数固定为AssertionError
:
scala> class X[A <: Throwable, B, C](b: B, c: C)
defined class X
scala> type XAssertionError[B, C] = X[AssertionError, B, C]
defined type alias XAssertionError
scala> val x = new XAssertionError(3,4)
x: X[java.lang.AssertionError,Int,Int] = X@22fe135d
答案 3 :(得分:3)
这是我的解决方案:
scala> class X[A <: Throwable, B, C](b: B, c: C)
defined class X
scala> class Builder[A <: Throwable] {
| def apply[B, C](b: B, c: C) = new X[A,B,C](b,c)
| }
defined class Builder
scala> def X[A <: Throwable]: Builder[A] = new Builder[A]
X: [A <: Throwable]=> Builder[A]
scala> val x = X[AssertionError](3, 4)
x: X[AssertionError,Int,Int] = X@2fc709
答案 4 :(得分:1)
您可以使用默认参数定义构造函数。
scala> class X[A <: Throwable, B, C](b: B, c: C, clz:Class[_ <: A] = classOf[Nothing])
defined class X
scala> new X(1,2)
res0: X[Nothing,Int,Int] = X@16de4e1
scala> new X(1,2, classOf[AssertionError])
res1: X[AssertionError,Int,Int] = X@1e41869