scala - 泛型中的任何与下划线

2023-12-12

Scala 中以下泛型定义有何不同:

class Foo[T <: List[_]]

and

class Bar[T <: List[Any]]

我的直觉告诉我它们大致相同,但后者更明确。我发现前者可以编译但后者不能编译的情况,但无法指出确切的差异。

Thanks!

Edit:

我可以再加入另一个吗?

class Baz[T <: List[_ <: Any]]

好吧,我想我应该对此有自己的看法,而不是仅仅发表评论。抱歉,这会很长,如果您想要 TL;DR 跳到最后。

正如兰德尔·舒尔茨所说,这里_是存在类型的简写。即,

class Foo[T <: List[_]]

是一个简写

class Foo[T <: List[Z] forSome { type Z }]

请注意,与 Randall Shulz 的答案提到的相反(完全披露:我在这篇文章的早期版本中也弄错了,感谢 Jesper Nordenberg 指出),这与以下内容不同:

class Foo[T <: List[Z]] forSome { type Z }

它也不等同于:

class Foo[T <: List[Z forSome { type Z }]]

请注意,很容易出错(正如我之前的错误所示):兰德尔·舒尔茨的答案引用的文章的作者自己也出错了(请参阅评论),并在稍后修复了它。我对本文的主要问题是,在所示的示例中,存在性的使用应该可以使我们避免打字问题,但事实并非如此。去检查代码,然后尝试编译compileAndRun(helloWorldVM("Test")) or compileAndRun(intVM(42))。是的,无法编译。简单制作compileAndRun通用在A将使代码编译,并且会简单得多。 简而言之,这可能不是了解存在主义及其优点的最佳文章(作者本人在评论中承认该文章“需要整理”)。

所以我更推荐阅读这篇文章:http://www.artima.com/scalazine/articles/scalas_type_system.html,特别是名为“存在类型”和“Java 和 Scala 中的差异”的部分。

您应该从本文中得到的重要一点是,在处理非协变类型时,存在性非常有用(除了能够处理通用 java 类之外)。 这是一个例子。

case class Greets[T]( private val name: T ) {
  def hello() { println("Hello " + name) }
  def getName: T = name
}

这个类是通用的(还要注意它是不变的),但我们可以看到hello实际上没有使用任何类型参数(与getName),所以如果我得到一个实例Greets我应该总是能够调用它,无论如何T是。如果我想定义一个方法Greets实例并调用它的hello方法,我可以尝试这个:

def sayHi1( g: Greets[T] ) { g.hello() } // Does not compile

果然,这不能编译,因为T这里不知从何而来。

好吧,让我们使该方法通用:

def sayHi2[T]( g: Greets[T] ) { g.hello() }
sayHi2( Greets("John"))
sayHi2( Greets('Jack))

太好了,这有效。我们还可以在这里使用存在主义:

def sayHi3( g: Greets[_] ) { g.hello() }
sayHi3( Greets("John"))
sayHi3( Greets('Jack))

也有效。所以总而言之,使用存在主义并没有真正的好处(如sayHi3)超过类型参数(如sayHi2).

然而,如果Greets它本身作为另一个泛型类的类型参数出现。举例来说,我们要存储多个实例Greets(与不同的T)在列表中。让我们尝试一下:

val greets1: Greets[String] = Greets("John")
val greets2: Greets[Symbol] = Greets('Jack)
val greetsList1: List[Greets[Any]] = List( greets1, greets2 ) // Does not compile

最后一行无法编译,因为Greets是不变的,所以Greets[String] and Greets[Symbol]不能被视为Greets[Any]虽然String and Symbol两者都延伸Any.

好的,让我们尝试一下存在主义,使用简写符号_:

val greetsList2: List[Greets[_]] = List( greets1, greets2 ) // Compiles fine, yeah

这编译得很好,你可以按照预期做:

greetsSet foreach (_.hello)

现在,请记住,我们首先遇到类型检查问题的原因是Greets是不变的。如果它变成一个协变类(class Greets[+T])那么一切都会开箱即用,我们永远不需要存在主义。


总而言之,存在性对于处理泛型不变类很有用,但是如果泛型类不需要将自身显示为另一个泛型类的类型参数,那么您很可能不需要存在性,只需添加类型参数即可你的方法会起作用

现在回到你的具体问题(最后,我知道了!)

class Foo[T <: List[_]]

Because List是协变的,这对于所有意图和目的来说都与刚才说的相同:

class Foo[T <: List[Any]]

所以在这种情况下,使用任何一种表示法实际上只是一个风格问题。

但是,如果您更换List with Set, 事情会改变的:

class Foo[T <: Set[_]]

Set是不变的,因此我们处于与Greets我的例子中的类。因此上面的内容确实与

class Foo[T <: Set[Any]]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala - 泛型中的任何与下划线 的相关文章

随机推荐

  • 使用 Apache poi 在堆叠条上方显示 SUM 值

    我目前正在研究功能 应该在 pptx 文件内生成堆叠图表 为此 我使用这里的代码 java 使用 APACHE POI 在 powerpoint 中创建图表 我做了一些修改 主要是我将分组设置为 堆叠 并将重叠设置为 100 因此子栏看起来
  • 测试 jQuery 可选择 capybara 或 selenium (ctrl + click)

    我正在使用 jQuery Selectable 来管理日历 这个功能很好用 只需进入测试自动化即可 我需要从日历网格中选择多个不连续的日期 我尝试了一些方法 但并不真正期望它们能起作用 date 2013 05 02 page execut
  • Verilog HDL ?操作员

    什么是 用 Verilog 做什么 例如 以下命令是什么意思 input first din input 7 0 din output 127 0 parity reg 127 0 parity wire 7 0 feedback assi
  • 排除 $lookup 聚合中的字段

    我正在查询 3 个要排除的集合 id输出中随处可见 我的输出是 id ObjectId 5b6aed5f9bcdb5d4ae64aef5 userID 1 skills id ObjectId 5b766b5f1365a4940bb6050
  • 产品设置中的自定义复选框,选中时显示自定义字段

    我目前正在使用 WooCommerce 开发 WordPress 电子商务网站 我在产品编辑页面常规设置中创建了一个自定义复选框 我还有一个代码片段 用于在单个产品页面中显示自定义文本字段 现在 我希望当为产品选中此自定义复选框 在其设置中
  • RealityKit – 如何以编程方式访问场景中的属性?

    我一直通过从库下载来使用现实作曲家和框架实体 我想访问对象的属性 以编程方式提供要在框架中显示的图像 在这里您可以看到有一个配置 我可以从我的画廊导入照片 但我想以编程方式完成它 也就是说 我想访问框架对象的该属性并以编程方式提供图像 但我
  • Spark-HBase - GCP模板(2/3) - json4s的版本问题?

    我正在尝试在 GCP 上下文中测试 Spark HBase 连接器并尝试遵循1 它要求使用 Maven 我尝试过 Maven 3 6 3 为 Spark 2 4 本地打包连接器 2 并在提交作业时出现以下错误Dataproc 完成 3 之后
  • PrimeFaces Piechart:工具提示未在我的本地环境中显示

    我重新创建了 primefaces 展示中显示的示例页面 http www primefaces org showcase ui chart pie xhtml 饼图成功显示 我可以调整饼图模型以获取可用的 setter 和 getter
  • 从 dynamodb 流读取数据

    我为我的发电机表设置了流 我正在按照文档中的示例程序从流中读取数据 http docs aws amazon com amazondynamodb latest developerguide Streams LowLevel Walkthr
  • 快照视频作为预览

    我在从视频中获取快照用作标题图像时遇到问题 下面有我当前使用的代码 但我得到的输出只是一个黑色图像 在控制台中我没有遇到任何问题 我将视频上传到我使用的文件服务器后执行此操作 let video videoPath find newVide
  • symfony 的 require_once

    我现在正在使用 php Symfony2 框架进行制作 并且我有以下代码 require once one file php require once another file php 等等 问题是 如何将这些不舒服的require语句 S
  • CSS 文本填充差异 Firefox 与 Chrome 等

    如果有人可以在以下方面提供帮助 我将不胜感激 因为我花了整个晚上在这个问题上没有结果 我有一个网站 我想在每篇文章之后修改标签外观 问题在于 firefox 版本 14 0 1 为文本提供了较小的高度 总 高度为 15px icnludin
  • 访问作为泛型类型传递的类属性

    我有两个类 它们被传递给序列化方法 我想在序列化方法中访问这些类的两个属性 问题是序列化方法参数作为泛型类型传递 我不知道在这种情况下如何访问传递的类的属性 下面的例子 public class MyClass1 public string
  • 在另一个框架的上下文中运行 JQuery

    我正在合作的客户有一个像这样的框架集 当发生某个操作时 我需要我的框架 当前隐藏的重要框架 主要接管页面并阻止与其他框架的任何交互 我计划使用 jquery block UI 插件来阻止交互 问题是我实际上无法更改 foo ht
  • 如何将结果写入JTextArea

    我有问题 如何将结果 数据库选择写入 JTextArea 我的 JButton 的方法是 public void actionPerformed ActionEvent evt try Class forName com mysql jdb
  • 使用 Graph API 获取所有 Facebook 好友

    我尝试获取 me friends 返回的 JSON 包含的朋友比我的 Facebook 页面显示的少 3 个 事实证明 对于这 3 个 GET id 返回 false 而不是有效的 JSON 对象 尽管我没有看到它们有什么特别之处 只是它们
  • Mongodb find查询返回空数组

    我试图通过代码 id 获取产品 但结果是空数组 我的控制器 export const getProductByPLU async req res gt const searchPLU req query try const product
  • 自动滚动jetpack compose中后面的项目

    我有一个3 Column In 1st Column的组件是2nd and 3rd Column In 2nd Column里面有很多组件 最后3rd Column我有一些项目 但我停留在屏幕底部 我已经在这个的帮助下完成了answer 在
  • 与 PhP 一起使用的 AMP 表单

    我正在尝试使用 AMP 设置带有联系表单的页面 该表单只有 4 个字段 Name Email 我们能帮你什么吗 电话号码 然后我希望将该信息发送到我的电子邮件地址 这是我在 HTML 中的信息 h4 How can we help h4
  • scala - 泛型中的任何与下划线

    Scala 中以下泛型定义有何不同 class Foo T lt List and class Bar T lt List Any 我的直觉告诉我它们大致相同 但后者更明确 我发现前者可以编译但后者不能编译的情况 但无法指出确切的差异 Th