【问题标题】:scala value class multiple inheritancescala值类多重继承
【发布时间】:2016-12-05 18:23:37
【问题描述】:

我的项目中有代表 ID 的对象。

假设它是ChairId、TableId、LampId。我希望它们都继承自 GenericId。我希望能够拨打def f(x: GenericId) = x.id

我希望他们只持有一个 id: String,所以我想让他们扩展 AnyVal。

我还希望每种类型都提供函数generate,它会生成我的特定ID,即我想输入类似ChairId.generate()的东西

我已经输入了这个:

sealed abstract class GenericId(val id: String)
final case class ChairId(override val id: String) extends GenericId(id)
final case class TableId(override val id: String) extends GenericId(id

而且我虽然如果 GenericId 会从 AnyVal 继承,那将起作用,但到目前为止还没有运气;/ 我还尝试使 GenericId 成为一个特征,并使案例类使用 GenericId 扩展 AnyVal,但也不会编译:/

TableId.generate() 的另一件事我可以仅使用函数 generate 提供伴随对象,这基本上解决了我的问题,但我想知道是否有可能在不定义伴随对象的情况下解决这个问题? (即通过某种方式隐含)

// 编辑

关于提供无法编译的代码的注释(我愿意):

sealed abstract class AbstractId(val id: String) extends AnyVal
final case class CatId(override val id: String) extends AbstractId(id)
final case class DogId(override val id: String) extends AbstractId(id)

【问题讨论】:

  • 我不完全确定你在这里问什么。如果有多个问题,您可能希望将它们拆分为多个 Stack Overflow 问题。
  • 请包含您尝试过的代码和编译错误。我认为这会有所帮助。

标签: scala inheritance value-class


【解决方案1】:

由于几个原因,值类不能以这种方式工作。

首先,从documentation开始,值类不能被任何其他类扩展,所以AbstractId不能扩展AnyVal。 (Limitation #7)

scala> abstract class AbstractId(val id: String) extends AnyVal
<console>:10: error: `abstract' modifier cannot be used with value classes
       abstract class AbstractId(val id: String) extends AnyVal
                      ^

第二,即使你将AbstractId设为特征,并像这样定义其他ID:

final case class DogId(val id: String) extends AnyVal with AbstractId

.. 值类的用法不适合您的情况,因为类本身仍会被分配。见allocation summary

值类在以下情况下实际实例化:

  1. 值类被视为另一种类型。
  2. 一个值类被分配给一个数组。
  3. 进行运行时类型测试,例如模式匹配。

【讨论】:

  • 你打了我几秒 :)
【解决方案2】:

来自value classes SIP 的一些引用可能会澄清您的疑问:

值类...

  1. ...必须只有一个主构造函数,其中只有一个 public, val 类型不是值类的参数。

  2. ...不能被其他类扩展。

根据1.不能是抽象的;每 2. 你的编码不​​起作用。

还有一个警告:

值类只能扩展通用特征,不能扩展 本身。通用特征是扩展 Any 的特征,只有 defs 作为成员,并且不进行初始化。通用特征允许基本 继承值类的方法,但它们会产生开销 分配。

考虑到所有这些,根据您上次的 sn-p,这可能有效:

sealed trait AbstractId extends Any { def id: String }
final case class CatId(id: String) extends AnyVal with AbstractId
final case class DogId(id: String) extends AnyVal with AbstractId

但请记住,仅当您想使用 CatId 和 DogId 作为 AbstractId 时才会进行分配。为了更好地理解,我建议阅读 SIP。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    • 2013-11-19
    • 2017-02-04
    相关资源
    最近更新 更多