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

我想摆脱运行时强制转换为泛型(asInstanceOf [A])而不进行隐式转换.

我有一个相当干净的数据模型,包含具有共同特征的案例类并希望在其上实现通用算法时,就会发生这种情况.作为一个例子,生成的算法应该采用类型A的类,它是特征T的子类,并且应该返回具有一些更新字段的具体类A的副本.

当我可以简单地将抽象复制方法添加到基本特征并在所有子类中实现它时,这很容易实现.然而,这可能会使用某些算法仅需要的方法来污染模型,有时不可能,因为模型可能不受我的控制.

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

请不要挂断细节.

假设有一个特征和一些我不能改变的案例类:

trait Share {
  def absolute: Int  
}

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

case class PreferredShare(
    issuedOn: String,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,0.25)

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

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

解决方法

你有几个我能想到的选择,它主要归结为你想要的解决方案的一般性以及你可以容忍的冗长程度.

asInstanceOf

你的解决方案感觉很脏,但我认为它并不是那么糟糕,并且gnarliness非常好.

类型类

为数据类型提供行为同时仍然保持代码中关注点分离的一种很好的方法是Enrich Your Library / typeclass模式.我希望我有一个完美的参考,但我没有.查找这些术语或“隐含类”,你应该能够找到足够的例子来获得漂移.

您可以创建一个特性copyable [A] {def copy(?):A}类型类(隐式类)并为每个类型创建它的实例.这里的问题是它有点冗长,特别是如果你想让复制方法完全通用的话.我把它的参数列表作为一个问号留下了,因为你可以根据实际需要将其简单地定制,或者你可以尝试让它适用于任何案例类,这将非常困难.

光学

镜头是为解决这种尴尬而制作的.您可能想查看Monocle,这是解决此问题的一个很好的通用方法.虽然它仍然没有真正解决冗长问题,但如果你在整个项目中反复出现这个问题,可能就是要走的路,特别是如果你发现自己试图在对象图中深入进行更改.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...