Scala:运行时替换方法



假设我有一个class

class Original {
  def originalMethod = 1
}

现在,假设我有一个实例

val instance = new Original

现在是否可以在运行时对instance做一些事情,用不同的方法替换originalMethod ?(假定签名保持不变)

例如,现在,当调用instance.originalMethod时,下面的代码将被称为println("test"); 1

编辑我不能打电话给new Original。我只有它的一个现有实例,我需要修改它。

编辑2 (@Aleksey Izmailov回答)这是一个很好的解决方案,但并不是我想要的。我想更多的是在测试方面-"正常"编写类,不指定函数作为变量而不是方法

p。当我试图模仿一个Mockito间谍时,我无意中发现了这个问题

似乎你必须恢复到突变,因为你不能有新的实例和行为必须改变。下面可能是最简单的选项(REPL):

将函数存储为可变字段:

scala> class Original {
     |   var originalMethod = () => 1
     | }
defined class Original
scala> val obj = new Original
obj: Original = Original@66ac5762

这是一个不带任何参数的函数,你需要调用apply()才能得到结果。

scala> obj.originalMethod
res0: () => Int = <function0>
scala> obj.originalMethod()
res1: Int = 1                       ^

用新函数替换:

scala> obj.originalMethod = () => 2
obj.originalMethod: () => Int = <function0>

现在你得到新的行为:

scala> obj.originalMethod()
res2: Int = 2

有趣的是,你不能在这个类的泛型版本中使用默认实现,因为没有默认值可以使用,除非你将其更改为Unit或部分函数。

这是它的通用版本:

scala> class Original[T] {                                                               
     |   var originalMethod: () => T = null                                              
     | }                                                                                 
defined class Original                                                                   
scala> val genImpl = new Original[Int] { originalMethod = () => 111 }                    
genImpl: Original[Int] = $anon$1@6b04acb2                                                       
scala> genImpl.originalMethod()                                                          
res8: Int = 111                                                                          
scala> genImpl.originalMethod = () => 222
genImpl.originalMethod: () => Int = <function0>
scala> genImpl.originalMethod()
res9: Int = 222

这在JVM上是不可能的-在Java或Scala中-不是以您要求的方式。

参见:在Java中,给定一个对象,是否有可能重写其中一个方法?

使用Scala而不是Java并不会给你带来额外的优势,因为Scala中类和方法的基本原理与Java是一样的。(这样做是出于性能和互操作的考虑。)

相关内容

  • 没有找到相关文章

最新更新