scala 值 class 多重继承
scala value class multiple inheritance
我的项目中有代表 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 成为特征并使案例 类 扩展 AnyVal 与 GenericId 但也不会编译: /
关于 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)
值 classes 不能以这种方式工作有几个原因。
首先来自documentation, value classes cannot be extended by any other class, so AbstractId
cannot extend 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
成为特征,并像这样定义其他ids:
final case class DogId(val id: String) extends AnyVal with AbstractId
.. 值 class 的用法不适合您的情况,因为 class 本身仍会被分配。见 allocation summary:
A value class is actually instantiated when:
- a value class is treated as another type.
- a value class is assigned to an array.
- doing runtime type tests, such as pattern matching.
value classes SIP 中的一些引述可能会澄清您的疑虑:
值类...
...must have only a primary constructor with exactly one public, val
parameter whose type is not a value class.
... cannot be extended by another class.
根据1.不能抽象;每 2. 你的编码不起作用。
还有一个警告:
A value class can only extend universal traits and cannot be extended
itself. A universal trait is a trait that extends Any, only has defs
as members, and does no initialization. Universal traits allow basic
inheritance of methods for value classes, but they incur the overhead
of allocation.
考虑到所有这些,根据您的最后一个片段,这可能有效:
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。
我的项目中有代表 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 成为特征并使案例 类 扩展 AnyVal 与 GenericId 但也不会编译: /
关于 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)
值 classes 不能以这种方式工作有几个原因。
首先来自documentation, value classes cannot be extended by any other class, so AbstractId
cannot extend 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
成为特征,并像这样定义其他ids:
final case class DogId(val id: String) extends AnyVal with AbstractId
.. 值 class 的用法不适合您的情况,因为 class 本身仍会被分配。见 allocation summary:
A value class is actually instantiated when:
- a value class is treated as another type.
- a value class is assigned to an array.
- doing runtime type tests, such as pattern matching.
value classes SIP 中的一些引述可能会澄清您的疑虑:
值类...
...must have only a primary constructor with exactly one public, val parameter whose type is not a value class.
... cannot be extended by another class.
根据1.不能抽象;每 2. 你的编码不起作用。
还有一个警告:
A value class can only extend universal traits and cannot be extended itself. A universal trait is a trait that extends Any, only has defs as members, and does no initialization. Universal traits allow basic inheritance of methods for value classes, but they incur the overhead of allocation.
考虑到所有这些,根据您的最后一个片段,这可能有效:
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。