Scala:引用嵌套类的类,它作为泛型的类型参数

时间:2014-12-08 09:11:44

标签: scala

我想实现类,它描述了有关设置某个选项值的操作。我想让选项的值类型取决于选项类型。我想做到这一点:

case class SetOptionMessage[T <: BaseOptionType](
    option: T
    value: Option[T#ValueType]
)

abstract class BaseOptionType {
    type ValueType
}


object SomeBooleanOption extends BaseOptionType {
    final type ValueType = Boolean
}

但是当我尝试使用这样的类时:

val msg = SetOptionMessage(SomeBooleanOption, Some(true))

我收到了编译错误:

Error:(15, 43) type mismatch;
found   : Some[Boolean]
required: Option[?#ValueType]
SetOptionMessage(SomeBooleanOption, Some(true))
                                      ^

如何正确引用嵌套类型?

2 个答案:

答案 0 :(得分:5)

类型成员

case class SetOptionMessage[V, T <: BaseOptionType{ type ValueType = V }](
  option: T,
  value: Option[V]
)

val msg = SetOptionMessage(SomeBooleanOption, Some(true))
// msg: SetOptionMessage[Boolean,SomeBooleanOption.type] = SetOptionMessage(SomeBooleanOption$@2e93ebe0,Some(true))

隐含证据

case class SetOptionMessage[V, T <: BaseOptionType](
  option: T,
  value: Option[V])(implicit e: V =:= T#ValueType)

SetOptionMessage(SomeBooleanOption, Some(true))
// SetOptionMessage[Boolean,SomeBooleanOption.type] = SetOptionMessage(SomeBooleanOption$@2e93ebe0,Some(true))

SetOptionMessage(SomeBooleanOption, None)
// SetOptionMessage[SomeBooleanOption.ValueType,SomeBooleanOption.type] = SetOptionMessage(SomeBooleanOption$@2e93ebe0,None)

不同的参数组

您无法在此解决方案中使用case class

class SetOptionMessage[T <: BaseOptionType](option: T)(val value: Option[T#ValueType])

val msg = new SetOptionMessage(SomeBooleanOption)(Some(true))
// SetOptionMessage[SomeBooleanOption.type] = SetOptionMessage@7f216e0c

msg.value
// Option[SomeBooleanOption.ValueType] = Some(true)

不安全的类别演员

不要使用它。

答案 1 :(得分:1)

ValueType是一种与路径相关的类型。这意味着您无法使用#访问它,SetOptionMessage只能引用非路径相关的类型。

尝试将case class SetOptionMessage[T <: BaseOptionType](val option: T, private val _value: Option[Any]) { val value = _value.asInstanceOf[Option[option.ValueType]] } 更改为:

val msg = SetOptionMessage(SomeBooleanOption, Some("hello"))

但是,您不应该使用此解决方案(请参阅下面的注释)。我保留答案未被发现,以揭露其问题。

注意

正如@senia在他的回答中指出的那样,这是最糟糕的解决方案,因为它依赖于类强制转换。这个演员提出了一些限制,因为这个SO答案中突出显示: https://stackoverflow.com/a/6690611/1893995

表达式:

{{1}}

不仅会编译,而且甚至会在运行时崩溃。