gpt4 book ai didi

scala - 从没有运行时强制转换的泛型函数返回 case 类的副本

转载 作者:行者123 更新时间:2023-12-04 19:04:31 25 4
gpt4 key购买 nike

我想在没有隐式转换的情况下摆脱对泛型( asInstanceOf[A] )的运行时强制转换。

当我有一个由具有共同特征的案例类组成的相当干净的数据模型并希望在其上实现通用算法时,就会发生这种情况。例如,结果算法应采用 A 类型的类。那是 trait T 的子类并且应该返回具体类 A 的副本有一些更新的领域。

当我可以简单地添加一个抽象 copy 时,这很容易实现。 -方法到基本特征并在所有子类中实现。然而,这可能会使用某些算法所需的方法污染模型,有时这是不可能的,因为模型可能超出我的控制。

这是一个使用运行时强制转换来演示问题和解决方案的简化示例。

请不要拘泥于细节。

假设有一个特征和一些我无法更改的案例类:

trait Share {
def absolute: Int
}

case class CommonShare(
issuedOn: String,
absolute: Int,
percentOfCompany: Float)
extends Share

case class PreferredShare(
issuedOn: String,
absolute: Int,
percentOfCompany: Float)
extends Share

这里有一个简单的方法来重新计算当前 percentOfCompany当股份总数发生变化并更新案例类中的字段时
def recalculateShare[A <: Share](share: A, currentTotalShares: Int): A = {

def copyOfShareWith(newPercentage: Float) = {
share match {
case common: CommonShare => common.copy(percentOfCompany = newPercentage)
case preferred: PreferredShare => preferred.copy(percentOfCompany = newPercentage)
}
}

copyOfShareWith(share.absolute / currentTotalShares.toFloat).asInstanceOf[A]
}

REPL 上的一些示例调用:
scala> recalculateShare(CommonShare("2014-01-01", 100, 0.5f), 400)
res0: CommonShare = CommonShare(2014-01-01,100,0.25)

scala> recalculateShare(PreferredShare("2014-01-01", 50, 0.5f), 400)
res1: PreferredShare = PreferredShare(2014-01-01,50,0.125)

所以它有效,据我所知 .asInstanceOf[A]调用永远不会失败,但需要编译代码。有没有办法在没有隐式转换的情况下以类型安全的方式避免运行时强制转换?

最佳答案

你有几个我能想到的选择,它主要归结为你想要的解决方案的通用性和你可以容忍的冗长程度之间的平衡。

asInstanceOf

您的解决方案感觉很脏,但我认为它并没有那么糟糕,而且粗糙程度得到了很好的控制。

类型分类

为数据类型提供行为同时仍保持代码中关注点分离的一种很好的方法是丰富您的库/类型类模式。我希望我有一个完美的引用,但我没有。查找这些术语或“隐式类”,您应该能够找到足够的示例来了解偏差。

您可以创建一个 trait Copyable[A] { def copy(?): A } typeclass ( implicit class ) 并为每个类型创建它的实例。这里的问题是它有点冗长,特别是如果你想要 copy方法是完全通用的。我将其参数列表留为问号,因为您可以根据实际需要对其进行严格定制,或者您可以尝试使其适用于任何 case class ,据我所知,这将是相当困难的。

光学

镜头就是为了解决这种尴尬而制作的。您可能想查看 Monocle ,这是一个很好的通用方法来解决这个问题。尽管它仍然不能真正解决冗长的问题,但如果您在整个项目中反复出现此问题,这可能是一种可行的方法,尤其是当您发现自己试图在对象图中进行深入更改时。

关于scala - 从没有运行时强制转换的泛型函数返回 case 类的副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28680721/

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