scala - 从种类中提取类型
问题描述
我想提取一种类型的类型,并用它来定义函数的返回类型。
例如。
让我们定义一个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
}
这样(我希望)想要实现 a 的用户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]): _$2 (defined in trait ContainerExtractor);
found : (container: Test.Container[String] with Test.Extra[Int])String
required: (container: Test.Container[String] with Test.Extra[Int])_$2
因为编译器无法推断通配符 in 引用的类型在此 trait 实现中C <: Container[_]
是 a 。String
关于如何避免让用户在实施时定义容器类型两次的任何帮助ContainerExtractor
?
解决方案
类型投影通过 usingClass#T
给出了来自 Class 的泛型成员类型,而不是 Class 实例。在您的情况下,如果您只是这样做C#Contained
,它只是指 C 的成员类型。编译器不知道 C 是什么。您应该改为从变量中获取成员类型:
trait ContainerExtractor[C <: Container[_]] {
def extract(container: C): container.Contained
}
推荐阅读
- sql - 如何正确使用 pg_dump 进行数据库迁移?
- python - 在卫星数据集上进行光谱聚类后使用 Networkx 制作图形
- javascript - Safari scrollY 在插入/删除元素时不会改变
- excel - 如何连续获得前 n 个非零值?
- linux - 如何设置http_proxy并使用它
- reactjs - 在 Netlify 上部署后未应用 Tailwind 样式
- shopify - Shopify 如何清除购物车的属性?
- r - 在ggplot中制作双条形图
- javascript - 为什么 event.button 在 Chrome 中无法与 mousedown 事件一起正常工作?
- selenium - 从 python 中的 URL 获取 html 和图像:HTTP 错误 403 或带有验证码的受 Cloudflare 保护的页面