gpt4 book ai didi

class - 带有父类(super class)的案例类副本 'method'

转载 作者:行者123 更新时间:2023-12-03 10:21:21 26 4
gpt4 key购买 nike

我想做这样的事情:

sealed abstract class Base(val myparam:String)

case class Foo(override val myparam:String) extends Base(myparam)
case class Bar(override val myparam:String) extends Base(myparam)

def getIt( a:Base ) = a.copy(myparam="changed")

我不能,因为在 getIt 的上下文中,我没有告诉编译器每个 Base 都有一个“复制”方法,但复制也不是真正的方法,所以我认为没有特征或抽象方法我可以放入 Base 以使其正常工作。或者,有吗?

如果我尝试将 Base 定义为 abstract class Base{ def copy(myparam:String):Base } ,然后 case class Foo(myparam:String) extends Base结果 class Foo needs to be abstract, since method copy in class Base of type (myparam: String)Base is not defined
有没有其他方法可以告诉编译器所有 Base类将是其实现中的案例类?某些特征意味着“具有案例类的属性”?

我可以使 Base 成为一个案例类,但随后我收到编译器警告,说不推荐使用从案例类继承?

我知道我还可以:

def getIt(f:Base)={ 
(f.getClass.getConstructors.head).newInstance("yeah").asInstanceOf[Base]
}

但是……这看起来很丑陋。

想法?我的整个方法只是“错误”吗?

更新 我更改了基类以包含该属性,并使案例类使用“覆盖”关键字。考虑到 Edmondo1984 的响应,这更好地反射(reflect)了实际问题,并使问题更加现实。

最佳答案

TL;DR: 我设法在 Base 上声明了 copy 方法,同时仍然让编译器在派生的案例类中自动生成其实现。这涉及到一个小技巧(实际上我自己只是重新设计了类型层次结构),但至少它表明您确实可以在不编写任何派生案例类中的样板代码的情况下使其工作。

首先,正如 ron 和 Edmondo1984 已经提到的,如果你的案例类有不同的字段,你会遇到麻烦。

不过,我将严格遵循您的示例,并假设您所有的案例类都具有相同的字段(查看您的 github 链接,这似乎也是您的实际代码的情况)。

鉴于您所有的案例类都具有相同的字段,自动生成的 copy方法将具有相同的签名,这是一个好的开始。那么在 Base 中添加通用定义似乎是合理的。 ,就像你做的那样:abstract class Base{ def copy(myparam: String):Base }现在的问题是 scala 不会生成 copy方法,因为基类中已经有一个。

事实证明,还有另一种方法可以静态确保 Base有权利copy方法,它是通过结构类型和自类型注释:

type Copyable = { def copy(myParam: String): Base }
sealed abstract class Base(val myParam: String) { this : Copyable => }

与我们之前的尝试不同,这不会阻止 scala 自动生成 copy方法。
最后一个问题:自类型注释确保 Base 的子类有一个 copy方法,但它不会在 Base 上公开提供:
val foo: Base = Foo("hello")
foo.copy()
scala> error: value copy is not a member of Base

为了解决这个问题,我们可以添加一个从 Base 到 Copyable 的隐式转换。一个简单的 Actor 就可以了,因为 Base 保证是可复制的:
implicit def toCopyable( base: Base ): Base with Copyable = base.asInstanceOf[Base with Copyable]

总结一下,这给了我们:
object Base {
type Copyable = { def copy(myParam: String): Base }
implicit def toCopyable( base: Base ): Base with Copyable = base.asInstanceOf[Base with Copyable]
}
sealed abstract class Base(val myParam: String) { this : Base. Copyable => }

case class Foo(override val myParam: String) extends Base( myParam )
case class Bar(override val myParam: String) extends Base( myParam )

def getIt( a:Base ) = a.copy(myParam="changed")

额外效果:如果我们尝试用不同的签名定义一个案例类,我们会得到一个编译错误:
case class Baz(override val myParam: String, truc: Int) extends Base( myParam ) 
scala> error: illegal inheritance; self-type Baz does not conform to Base's selftype Base with Base.Copyable

最后,一个警告:您可能应该只修改您的设计以避免不得不诉诸上述技巧。
在您的情况下,ron 建议使用单个案例类和额外的 etype领域似乎很合理。

关于class - 带有父类(super class)的案例类副本 'method',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12370244/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com