scala值类多重继承



我的项目中有表示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作为一种特性,并使case类使用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)

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

首先,从文档来看,值类不能由任何其他类扩展,因此AbstractId不能扩展AnyVal。(限制#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

value类的用法不适合您的情况,因为类本身仍然会被分配。参见分配摘要:

当:时,值类实际上被实例化

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

价值类SIP中的一些引号可能会澄清您的疑虑:

值类。。。

  1. 。。。必须只有一个只有一个公共val的主构造函数类型不是值类的参数。

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

按照1。它不能是抽象的;按照2。你的编码不起作用。

还有一个警告:

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

考虑到所有这些,根据您的最后一个片段,这可能会奏效:

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。

相关内容

  • 没有找到相关文章

最新更新