从种类中提取类型
Extract type from kind
我想提取一种类型,并用它来定义函数的return类型。
例如
让我们定义一个 Container
特征。
trait Container[T] {
def contained: T
}
让我们定义一个 Extra
特征,这样我们就可以从我们的容器中扩展它。
trait Extra[T] {
def extra: T
}
让我们定义一个特征 ContainerExtractor
为
trait ContainerExtractor[T, C <: Container[T]] {
def extract(container: C): T
}
现在用户可以通过
实现ContainerExtractor
new ContainerExtractor[String, Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String = ???
}
不错,虽然用户需要在Container
里面声明类型两次!
[String, Container[String] ... ]
为了解决这个重复问题,我尝试通过将 Container
和 ContainerExtractor
重新定义为
来解决这个问题
trait Container[T] {
def contained: T
final type Contained = T
}
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): C#Contained
}
这样(我希望)想要实现 ContainerExtractor
的用户可以写:
new ContainerExtractor[Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String =???
}
虽然这失败了:
incompatible type in overriding
def extract(container: Test.Container[String] with Test.Extra[Int]): _ (defined in trait ContainerExtractor);
found : (container: Test.Container[String] with Test.Extra[Int])String
required: (container: Test.Container[String] with Test.Extra[Int])_
因为编译器无法推断 C <: Container[_]
中通配符所引用的类型是此特征实现中的 String
。
关于如何避免用户在实施时定义容器类型两次的任何帮助 ContainerExtractor
?
使用 Class#T
的类型投影给出了 Class 的通用成员类型,而不是 Class 实例。在你的情况下,如果你只是做 C#Contained
,它只是指 C 的成员类型。编译器不知道 C 是什么。您应该从变量中获取成员类型:
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): container.Contained
}
我想提取一种类型,并用它来定义函数的return类型。
例如
让我们定义一个 Container
特征。
trait Container[T] {
def contained: T
}
让我们定义一个 Extra
特征,这样我们就可以从我们的容器中扩展它。
trait Extra[T] {
def extra: T
}
让我们定义一个特征 ContainerExtractor
为
trait ContainerExtractor[T, C <: Container[T]] {
def extract(container: C): T
}
现在用户可以通过
实现ContainerExtractor
new ContainerExtractor[String, Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String = ???
}
不错,虽然用户需要在Container
里面声明类型两次!
[String, Container[String] ... ]
为了解决这个重复问题,我尝试通过将 Container
和 ContainerExtractor
重新定义为
trait Container[T] {
def contained: T
final type Contained = T
}
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): C#Contained
}
这样(我希望)想要实现 ContainerExtractor
的用户可以写:
new ContainerExtractor[Container[String] with Extra[Int]] {
override def extract(container: Container[String] with Extra[Int]): String =???
}
虽然这失败了:
incompatible type in overriding
def extract(container: Test.Container[String] with Test.Extra[Int]): _ (defined in trait ContainerExtractor);
found : (container: Test.Container[String] with Test.Extra[Int])String
required: (container: Test.Container[String] with Test.Extra[Int])_
因为编译器无法推断 C <: Container[_]
中通配符所引用的类型是此特征实现中的 String
。
关于如何避免用户在实施时定义容器类型两次的任何帮助 ContainerExtractor
?
使用 Class#T
的类型投影给出了 Class 的通用成员类型,而不是 Class 实例。在你的情况下,如果你只是做 C#Contained
,它只是指 C 的成员类型。编译器不知道 C 是什么。您应该从变量中获取成员类型:
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): container.Contained
}