尽管您确实指定了您正在使用的 json 序列化库,但几乎可以保证只需执行以下操作即可:
case class Asset(id: Option[Int], description: Option[String]= None, url = "images/" + id.toString+".png")
鉴于它url
无论如何都有一个默认值,将其转换为参数不会对您的代码产生负面影响(您仍然可以Asset(None)
像以前一样通过示例进行操作)。唯一的缺点是现在客户端代码可能会创建一个Asset
具有不同值的实例url
,这可能不是您想要的。
如果是这种情况,您可能需要为您的Asset
类创建自定义 json 格式,但在不知道您使用哪个序列化库的情况下,我在这方面无能为力。
更新:
糟糕,我完全错过了默认值url
取决于另一个参数 ( id
) 的事实(感谢@Kristian Domagala 的注意)。因此,我上面的代码段无法编译。一个简单的解决方案是url
按照@Kristian Domagala 的建议放入第二个参数列表:
case class Asset(id:Option[Int],description:Option[String]=None)(val url:String = "images/" + id.toString+".png")
但这可能并不理想,因为这改变了Asset
(url
在比较实例时不再考虑的相等语义),并且还改变了构造语法:当显式指定url
值时,您需要执行类似的操作Asset(Some(123))("gfx/myImage.png")
而不是示例Asset(Some(123), url="gfx/myImage.png")
. 如果你能忍受这些缺点,这肯定是最简单的解决方案。
否则,还有另一种解决方法:我们可以重新定义Asset.apply
自己(手动):
case class AssetImpl( val id: Option[Int], val description: Option[String], val url: Option[String]) {
override def productPrefix = "Asset"
}
type Asset = AssetImpl
object Asset {
def apply( id: Option[Int], description: Option[String] = None, url: Option[String] = None ) = {
new Asset( id, description, url.orElse( id.map( "images/" + _ + ".png") ) )
}
}
正如你所看到的,我已经变成url
了Option
一个默认值None
(避免以前的编译错误,因为它不再依赖id
),因为,并且我用默认值def apply...
实例化了(这是我实际获得值的地方的) 的。Asset
url
id
id.map( "images/" + _ + ".png")
其余的基本上只是能够重新定义的噪音Asset.apply
:事实证明,实际上您无法重新定义案例类的工厂(您只能添加单独的重载)。所以我将类重命名为AssetImpl
,添加了一个类型别名以便没有人注意到 ( ;-) ),并创建了我自己的对象Asset
,我在其中定义了apply
方法(它不再与自动生成的apply
方法冲突,因为这个在不同的AssetImpl
对象。我也可以简单地变成Asset
一个标准类(非案例类),但随后我将不得不重新定义equals
并且hashCode
我觉得更烦人,因为在向类添加/删除字段时必须维护它。