当前位置: 首页 > 知识库问答 >
问题:

是合理的,扩展AnyVal的Scala Symbol类有什么好处吗?

邢高澹
2023-03-14

似乎scala有一个问题。符号是它的两个对象,符号和它所基于的字符串。

为什么不能通过定义Sym来消除这个额外的对象,例如:

class Sym private(val name:String) extends AnyVal {
    override def toString = "'" + name
}

object Sym {
    def apply(name:String) = new Sym(name.intern)
}

诚然,对象分配对性能的影响可能很小,但与那些对Scala有更深入了解的人一起发表的评论将很有启发性。特别是,以上是否通过引用相等提供了有效的映射?

上面简单的“Sym”的另一个优点是,在以地图为中心的应用程序中,有许多字符串键,但字符串命名了许多完全不同的事物,可以定义类型安全的Sym类,以便地图将明确地向程序员、编译器和重构工具显示键的真正含义。

(Symbol和Sym都不能扩展,前者显然是自己选择的,后者是因为它扩展了AnyVal,但Sym很小,可以用一个合适的名称来复制)

共有3个答案

江鹏飞
2023-03-14

对于AnyVal,类实际上是String。神奇地添加的方法和类型安全只是编译器技巧。是String被传输到各处。

对于模式匹配(我认为Symbol的目的)Scala需要对象的类。因此-Symbol扩展AnyRef

郑宇
2023-03-14

不幸的是,每当将AnyVal放入集合时,都会强制为其分配对象,如示例中的映射。这是因为值类必须强制转换为集合的类型参数,而强制转换为新类型总是强制分配。这几乎消除了将Sym声明为值类的任何优势。有关值类,请参见Scala文档页面中的分配详细信息。

浦思源
2023-03-14

无法将符号作为AnyVal。与简单字符串相比,符号的主要优点是可以保证符号被插入,因此可以使用简单的引用比较而不是昂贵的字符串比较来测试符号的相等性。

请参阅符号的源代码。Equals被覆盖并重新定义以使用eq方法进行参考比较。

但不幸的是,AnyVal不允许您重新定义平等。对于用户定义的值类,请参阅SIP-15:

C可能没有定义具体的equals或hashCode方法。

因此,尽管有一种在不产生运行时开销的情况下重新定义相等性的方法非常有用,但不幸的是这是不可能的。

编辑:从不使用字符串。在任何表现重要的项目中实习。字符串的性能。与一张微不足道的实习生表格相比,实习生是可怕的。看看这个问题和答案。有关简单的intern表,请参阅上面Symbol的源代码。

 类似资料:
  • 问题内容: 我想在我的JS代码中扔一些东西,我希望它们是Error的instanceof,但我也想让它们成为其他东西。 在Python中,通常将Exception子类化。 在JS中适合做些什么? 问题答案: 在ES6中:

  • 扩展是可定制化浏览体验的小程序,它们使用户可以根据个人需要或者偏好定制 Chrome 的功能和行为。它们基于 Web 技术(例如 HTML,JavaScript 和 CSS)构建。 扩展必须满足狭义定义且易于理解的单一目的(译者注:功能简单易懂化)。一个扩展可以包括多个组件和一系列功能,只要所有的内容都有助于实现共同的目标。 用户交互界面应尽量小且有意图。他们的范围从简单的图标,如右侧显示的 Go

  • 问题内容: 这样的方法声明有什么区别: 还有这个: 我的看法是,他们两个都指定传入的对象 必须 是type的子类,那么在这种情况下为什么还要烦恼泛型呢? 问题答案: 在您的情况下,差别不大。 但是请考虑以下几点: 在这种情况下,您可以通过以下方式调用该方法: 如果您使用 您将只能执行以下操作:

  • 问题内容: 我是Java开发人员,我想知道如何在Java程序中使用Scala? 问题答案: 去阅读 Daniel Spiewak 关于Scala 的优秀博客系列。使用Scala,您可以保持: 您所有的Java库 在JVM上运行的所有优势(普遍性,管理工具,性能分析,垃圾回收等) 但是您可以编写Scala代码: 比Java更简洁明了(尤其是使用更多的 功能 样式,例如在collections库中)

  • 问题内容: 用Java导入和扩展类有什么区别 问题答案: 那是两件事。 导入一个类是为了使您可以使用该类,而无需在要编写的当前类中限定全名。 扩展类是创建一个新类,该新类是某个其他类的子类。这将允许您添加或更改要扩展的类的功能。