说我有更高的kinded类型
SuperMap[Key[_],Value[_]]`.
现在假设我有更具体的内容要求Key
的类型参数必须与Value
的类型参数相匹配;就是这样的事情:
SuperDuperMap[T, Key[T], Value[T]]
进一步假设我不想要任何T
,而是一个非常具体的T <: OtherT
SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]]
这可以在Scala中完成吗?这通常是一个坏主意吗?有没有相同的方法来做这个更容易阅读/写/使用?
答案 0 :(得分:11)
您的声明已按预期运行,即您限制T
以及Key
和Value
的类型。但是,如果您发布类似
scala> class Foo[T <: OtherT, Key[T], Value[T]]
defined class Foo
scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
<console>:13: error: Key[SpecialOtherT] takes no type parameters, expected: one
new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
因为您之前的声明已经提供了Key
和Value
的类型。因此这将起作用
scala> new Foo[SpecialOtherT, Key, Value]
res20: Foo[SpecialOtherT,Key,Value] = Foo@3dc6a6fd
这可能不是你想要的。你可以这样做
scala> class Foo[T <: OtherT, K <: Key[T], V <: Value[T]]
defined class Foo
scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
res21: Foo[SpecialOtherT,Key[SpecialOtherT],Value[SpecialOtherT]] = Foo@7110506e
在底线,由于Key
和Value
的类型完全取决于T
,因此在使用Foo
时获取所有冗余信息有点多余。那么为什么不使用这样的内部类型声明:
class Foo[T <: OtherT] {
type K = Key[T]
type V = Value[T]
}
然后您可以从班级中访问类型K
和V
,但每次创建新答案时都不需要输入类型:
scala> new Foo[SpecialOtherT]
res23: Foo[SpecialOtherT] = Foo@17055e90
scala> new Foo[Int]
<console>:11: error: ...
答案 1 :(得分:3)
可以在Scala中完成吗?
你是什么意思?你刚才做到了!这通常是一个坏主意吗?
为什么会这样?事实上,这是一个好主意!这就是高等级的类型。
是否有相同的方法可以更容易地进行读/写/使用?
阅读 - 对我来说非常好。
写作 - 编写/测试/编译一次,随处使用。
使用 - 编译器将重建(推断)“无处不在”的类型。
答案 2 :(得分:2)
你可能不需要比几个类型别名更复杂的东西,
type SuperDuperMap[T, Key[_], Value[_]] = SuperMap[Key, Value]
type SuperDuperPooperMap[T <: OtherT, Key[_], Value[_]] = SuperMap[Key, Value]
示例REPL会话,
scala> new SuperDuperMap[Int, Option, List] {}
res0: java.lang.Object with SuperDuperMap[Int,Option,List] = ...
scala> new SuperDuperPooperMap[OtherT, Option, List] {}
res1: java.lang.Object with SuperDuperPooperMap[OtherT,Option,List] = ...