Scala Case Class 伴随对象 - 类型名称冲突
Scala Case Class Companion Objects - Conflict on the type name
我遇到了伴随对象选择其类型而不是大小写的问题 class
我正在使用喷雾 json serdes。他们需要一个隐式的 JsonFormat。这种格式是通过调用一个函数来获得的,该函数取决于 case class 的参数数量: jsonFormat2(Class2) if case class 有两个字段,如
case class Class2(a: String, b: Integer)
或jsonFormat3(Class3) for
case class Class3(a: String, b: Integer, c: Long)
鉴于必须知道您的案例 class 在整个代码中的参数数量并不好,我想制作一个案例 class 伴随对象,以便您可以封装此信息并获得来自 class 本身的 JsonFormat,例如:
object Class2 extends DefaultJsonProtocol
{
def getJsonFormat() = {
jsonFormat2(Class2)
}
}
但是如果我这样做,我会遇到以下编译问题:
type mismatch;
[error] found : mypackage.Class2.type
[error] required: (?, ?) => ?
[error] jsonFormat2(Class2)
如果我们查看 jsonFormat2 中的代码,签名是:
def jsonFormat2[P1 :JF, P2 :JF, T <: Product :ClassManifest
(construct: (P1, P2) => T): RootJsonFormat[T] = { // ...
如果我更改伴随对象名称(例如更改为 MyClass2),它将正常工作。所以,看起来类型是冲突的。
似乎在处理打字时,伴生对象不能像 class 那样命名。
有人可以解释为什么会发生这种情况,是否存在限制,或者如何解决这个问题,以便可以使用相同的名称来使用伴生对象?
您对 object Class2
的定义没有扩展 (String, Integer) => Class2
。您可能希望显式传递 apply
-方法:
case class Class2(a: String, b: Integer)
object Class2 extends DefaultJsonProtocol
{
def getJsonFormat() = {
jsonFormat2(Class2.apply)
}
}
受到@AlexeyRomanov 的有用评论的启发,我决定添加一个稍微更详细的解释,解释为什么当你没有定义伴生对象时它会工作,以及为什么当你将它定义为 object Class2 { ... }
时它会停止工作。
如果编译
class Foo(n: Int, s: String)
那么自动生成的伴随对象的反编译代码如下:
public final class Foo$
extends AbstractFunction2<Object, String, Foo>
implements Serializable {
/* some lines omitted */
public Foo apply(int n, String s) {
return new Foo(n, s);
}
/* some lines omitted */
}
即扩展AbstractFunction2
,因此符合(?, ?) => ?
.
当你自己定义object Foo
时,生成的对象不会扩展
(Int, String) => Foo
。这就是为什么当您定义同伴时它停止工作的原因
自己反对而不扩展 Function
.
当隐式定义 Class2
的伴随对象时,它会扩展 (String, Integer) => Class2
;你的版本没有。如果你改成
object Class2 extends DefaultJsonProtocol with (String, Integer) => Class2 { ... }
它会起作用,但为了避免重复参数类型,我会采纳 Andrey Tyukin 的建议(即使解释不正确)。
我遇到了伴随对象选择其类型而不是大小写的问题 class
我正在使用喷雾 json serdes。他们需要一个隐式的 JsonFormat。这种格式是通过调用一个函数来获得的,该函数取决于 case class 的参数数量: jsonFormat2(Class2) if case class 有两个字段,如
case class Class2(a: String, b: Integer)
或jsonFormat3(Class3) for
case class Class3(a: String, b: Integer, c: Long)
鉴于必须知道您的案例 class 在整个代码中的参数数量并不好,我想制作一个案例 class 伴随对象,以便您可以封装此信息并获得来自 class 本身的 JsonFormat,例如:
object Class2 extends DefaultJsonProtocol
{
def getJsonFormat() = {
jsonFormat2(Class2)
}
}
但是如果我这样做,我会遇到以下编译问题:
type mismatch;
[error] found : mypackage.Class2.type
[error] required: (?, ?) => ?
[error] jsonFormat2(Class2)
如果我们查看 jsonFormat2 中的代码,签名是:
def jsonFormat2[P1 :JF, P2 :JF, T <: Product :ClassManifest
(construct: (P1, P2) => T): RootJsonFormat[T] = { // ...
如果我更改伴随对象名称(例如更改为 MyClass2),它将正常工作。所以,看起来类型是冲突的。
似乎在处理打字时,伴生对象不能像 class 那样命名。
有人可以解释为什么会发生这种情况,是否存在限制,或者如何解决这个问题,以便可以使用相同的名称来使用伴生对象?
您对 object Class2
的定义没有扩展 (String, Integer) => Class2
。您可能希望显式传递 apply
-方法:
case class Class2(a: String, b: Integer)
object Class2 extends DefaultJsonProtocol
{
def getJsonFormat() = {
jsonFormat2(Class2.apply)
}
}
受到@AlexeyRomanov 的有用评论的启发,我决定添加一个稍微更详细的解释,解释为什么当你没有定义伴生对象时它会工作,以及为什么当你将它定义为 object Class2 { ... }
时它会停止工作。
如果编译
class Foo(n: Int, s: String)
那么自动生成的伴随对象的反编译代码如下:
public final class Foo$
extends AbstractFunction2<Object, String, Foo>
implements Serializable {
/* some lines omitted */
public Foo apply(int n, String s) {
return new Foo(n, s);
}
/* some lines omitted */
}
即扩展AbstractFunction2
,因此符合(?, ?) => ?
.
当你自己定义object Foo
时,生成的对象不会扩展
(Int, String) => Foo
。这就是为什么当您定义同伴时它停止工作的原因
自己反对而不扩展 Function
.
当隐式定义 Class2
的伴随对象时,它会扩展 (String, Integer) => Class2
;你的版本没有。如果你改成
object Class2 extends DefaultJsonProtocol with (String, Integer) => Class2 { ... }
它会起作用,但为了避免重复参数类型,我会采纳 Andrey Tyukin 的建议(即使解释不正确)。