gpt4 book ai didi

scala - 使用 Scala 案例类作为事实上的映射

转载 作者:行者123 更新时间:2023-12-01 09:17:23 27 4
gpt4 key购买 nike

这比其他任何事情都更像是一个设计问题......

我真的很喜欢 Scala 的案例类并且经常使用它们。但是,我发现我经常将参数包含在 Options 中。 (或者更确切地说,Lift 的 Boxes )并设置默认值以实现灵活性并考虑到用户可能并不总是指定所有参数。我想我采用了这种做法。

我的问题是,这是一种合理的方法吗?鉴于一切都可能是可选的,可能会有很多样板和检查,以至于我怀疑我是否不只是使用我的案例类,如 Map[String, Any]并想知道我是否会更好地使用 Map .

让我给你一个真实的例子。在这里,我正在模拟汇款:

case class Amount(amount: Double, currency: Box[Currency] = Empty)
trait TransactionSide
case class From(amount: Box[Amount] = Empty, currency: Box[Currency] = Empty, country: Box[Country] = Empty) extends TransactionSide
case class To(amount: Box[Amount] = Empty, currency: Box[Currency] = Empty, country: Box[Country] = Empty) extends TransactionSide
case class Transaction(from: From, to: To)

我觉得比较容易理解。在这个最简单的情况下,我们可以声明一个 Transaction像这样:
val t = Transaction(From(amount=Full(Amount(100.0)), To(country=Full(US)))

我已经可以想象你认为它很冗长。如果我们指定所有内容:
val t2 = Transaction(From(Full(Amount(100.0, Full(EUR))), Full(EUR), Full(Netherlands)), To(Full(Amount(150.0, Full(USD))), Full(USD), Full(US)))

另一方面,尽管不得不抛出 Full在任何地方,你仍然可以做一些很好的模式匹配:
t2 match {
case Transaction(From(Full(Amount(amount_from, Full(currency_from1))), Full(currency_from2), Full(country_from)), To(Full(Amount(amount_to, Full(currency_to1))), Full(currency_to2), Full(country_to))) if country_from == country_to => Failure("You're trying to transfer to the same country!")
case Transaction(From(Full(Amount(amount_from, Full(currency_from1))), Full(currency_from2), Full(US)), To(Full(Amount(amount_to, Full(currency_to1))), Full(currency_to2), Full(North_Korea))) => Failure("Transfers from the US to North Korea are not allowed!")
case Transaction(From(Full(Amount(amount_from, Full(currency_from1))), Full(currency_from2), Full(country_from)), To(Full(Amount(amount_to, Full(currency_to1))), Full(currency_to2), Full(country_to))) => Full([something])
case _ => Empty
}

这是一个合理的方法吗?使用 Map 会为我提供更好的服务吗? ?或者我应该以不同的方式使用案例类?也许使用整个案例类层次结构来表示具有不同信息量的交易?

最佳答案

如果某些东西真的是可选的,那么你真的别无选择。 null不是 一个选项(没有双关语意)。

但是,我强烈建议不要使用 Lift 的 box 类型,除非您需要它来专门处理 Lift API。您只是引入了不必要的依赖项。

我还会认真考虑拥有一个 Amount 是否真的有意义。没有指定的货币。如果它是有效的,那么创建一个专用的“空对象”来表示一个未指定的货币会给你一个更清晰的 API:

class LocalCurrency extends Currency

或者:
sealed trait Amount
case class LocalisedAmount(value: Double, currency: Currency) extends Amount
case class RawAmount(value: Double) extends Amount

对于 TransactionSide子类,我觉得奇怪的是你可以指定 CurrencyAmount 分开(它已经嵌入了货币的概念)。我赞成:
case class TxEnd(
amount: Option[Amount] = None,
country: Option[Country] = None)
case class Transaction(from: TxEnd, to: TxEnd)

最后...

是的,如果 map 适合您的领域,请使用它们,它们将使代码更简洁。

关于scala - 使用 Scala 案例类作为事实上的映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6547409/

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