在 Scala 中,Inner case class 如何始终覆盖方法?
In Scala, how can an Inner case class consistently override a method?
我最近发现 Scala 编译器对案例 class 有一个有趣的特性:因为它生成一个 class 和一个对象签名,如果定义为内部 class,它可以用最少的样板代码覆盖抽象类型定义和它的超级class的函数定义,这里是一个例子:
object InnerCaseClassOverridingBoth {
trait AALike
trait SS {
type AA <: AALike
def AA(): AnyRef
}
trait SS_Clear extends SS {
def AA(): AnyRef
}
class SSA extends SS_Clear {
case class AA() extends AALike
}
object SSA extends SSA {}
}
这将编译而不会出现任何错误。然而,快捷方式到此为止,如果函数定义 def AA
被参数化,那么内部 case class 和内部对象都无法覆盖它:内部对象的 apply
函数不能t 自动扩展到其外部的方法 class:
trait SS_Parameterised extends SS {
def AA(ii: Int): AnyRef
}
class SSB extends SS_Parameterised {
case class AA(ii: Int) extends AALike
}
object SSB extends SSB {}
这给出了一个错误:
class SSB needs to be abstract, since method AA in trait
SS_Parameterised of type (ii: Int)AnyRef is not defined
class SSB extends SS_Parameterised {
我的问题是,这种情况下有捷径吗?为什么 Scala 编译器设计为 link 情况 1 而不是情况 2?
它根本不是特别设计的;或者,它是,但不是你想的那样。您不是用构造 AA
的方法覆盖 def AA()
,而是用 object AA
本身覆盖它。注意事项
trait T {
type I <: AnyRef
def I(): AnyRef
}
object O extends T {
case class I(val i: Int)
}
这很好用。
> (O: T).I()
I
> (O: T).I().getClass
class O$I$
> O.I(5)
I(5)
> O.I(5).getClass
class O$I
突出的设计选择是“object
s 可以覆盖无参数 def
s”(val
s、var
s 也可以,当然, 无参数 def
s) 和“case class
es 自动生成 object
s”。 "Inner case class
es override methods of the same name in their outer class with their constructors," 不是 Scala 的规则之一。 object O
包含一个case class I
和一个object I
,摘要def I(): AnyRef
被覆盖为return表示object I
。 object I
的内容无所谓,因为def I()
只需要return和AnyRef
,也就是说没有任何限制。完全有道理
trait U {
type I <: AnyRef
def I(i: Int): AnyRef
}
object P extends U {
case class I(i: Int)
}
那么失败。 object P
包含一个 case class I
和一个关联的 object I
,但它还需要一个 def I(i: Int): AnyRef
,而它缺少。
我猜这只是与 apply
在案例 类 中扮演的角色有关。参见 Case Class default apply method
SSA
通过 SSA
(SSA.apply
) 的伴随对象满足 SS_Clear.AA
。
当您向方法添加参数时,您不再有 0 参数 apply
方法来履行该角色。
好的,我找到了 2 种方法
方法 1:被大小写覆盖 class:
trait SS_Parameterised {
type AA <: AALike
def AA: Int => AnyRef
}
方法 2:被隐式覆盖 class:
trait SS_Parameterised {
type AA <: AALike
implicit def AA(ii: Int): AnyRef
}
class SSB extends SS_Parameterised {
implicit class AA(ii: Int) extends AALike
}
故事结束 :) 一个案例 class 覆盖了 2 个声明?没问题。
(方法 2 的工作原理是 scala 在内部为每个隐式 class 生成一个隐式函数)
我最近发现 Scala 编译器对案例 class 有一个有趣的特性:因为它生成一个 class 和一个对象签名,如果定义为内部 class,它可以用最少的样板代码覆盖抽象类型定义和它的超级class的函数定义,这里是一个例子:
object InnerCaseClassOverridingBoth {
trait AALike
trait SS {
type AA <: AALike
def AA(): AnyRef
}
trait SS_Clear extends SS {
def AA(): AnyRef
}
class SSA extends SS_Clear {
case class AA() extends AALike
}
object SSA extends SSA {}
}
这将编译而不会出现任何错误。然而,快捷方式到此为止,如果函数定义 def AA
被参数化,那么内部 case class 和内部对象都无法覆盖它:内部对象的 apply
函数不能t 自动扩展到其外部的方法 class:
trait SS_Parameterised extends SS {
def AA(ii: Int): AnyRef
}
class SSB extends SS_Parameterised {
case class AA(ii: Int) extends AALike
}
object SSB extends SSB {}
这给出了一个错误:
class SSB needs to be abstract, since method AA in trait
SS_Parameterised of type (ii: Int)AnyRef is not defined
class SSB extends SS_Parameterised {
我的问题是,这种情况下有捷径吗?为什么 Scala 编译器设计为 link 情况 1 而不是情况 2?
它根本不是特别设计的;或者,它是,但不是你想的那样。您不是用构造 AA
的方法覆盖 def AA()
,而是用 object AA
本身覆盖它。注意事项
trait T {
type I <: AnyRef
def I(): AnyRef
}
object O extends T {
case class I(val i: Int)
}
这很好用。
> (O: T).I()
I
> (O: T).I().getClass
class O$I$
> O.I(5)
I(5)
> O.I(5).getClass
class O$I
突出的设计选择是“object
s 可以覆盖无参数 def
s”(val
s、var
s 也可以,当然, 无参数 def
s) 和“case class
es 自动生成 object
s”。 "Inner case class
es override methods of the same name in their outer class with their constructors," 不是 Scala 的规则之一。 object O
包含一个case class I
和一个object I
,摘要def I(): AnyRef
被覆盖为return表示object I
。 object I
的内容无所谓,因为def I()
只需要return和AnyRef
,也就是说没有任何限制。完全有道理
trait U {
type I <: AnyRef
def I(i: Int): AnyRef
}
object P extends U {
case class I(i: Int)
}
那么失败。 object P
包含一个 case class I
和一个关联的 object I
,但它还需要一个 def I(i: Int): AnyRef
,而它缺少。
我猜这只是与 apply
在案例 类 中扮演的角色有关。参见 Case Class default apply method
SSA
通过 SSA
(SSA.apply
) 的伴随对象满足 SS_Clear.AA
。
当您向方法添加参数时,您不再有 0 参数 apply
方法来履行该角色。
好的,我找到了 2 种方法
方法 1:被大小写覆盖 class:
trait SS_Parameterised {
type AA <: AALike
def AA: Int => AnyRef
}
方法 2:被隐式覆盖 class:
trait SS_Parameterised {
type AA <: AALike
implicit def AA(ii: Int): AnyRef
}
class SSB extends SS_Parameterised {
implicit class AA(ii: Int) extends AALike
}
故事结束 :) 一个案例 class 覆盖了 2 个声明?没问题。
(方法 2 的工作原理是 scala 在内部为每个隐式 class 生成一个隐式函数)