我们说我有一个班级
class Original {
def originalMethod = 1
}
现在,让我们说我有一个实例
val instance = new Original
现在是否可以在运行时对instance
执行某些操作以使用其他方法替换originalMethod
? (授予签名保持不变)
例如,现在,在调用instance.originalMethod
时,将调用以下代码println("test"); 1
修改
我无法致电new Original
。我只有一个现有的实例,我必须修改它。
编辑2 (@Aleksey Izmailov回答)这是一个很好的解决方案,但并不是我正在寻找的。我在测试方面考虑更多 - 写一个类"通常",而不指定函数作为变量而不是方法
PS。当我试图模仿Mockito间谍时,我偶然发现了这个问题
答案 0 :(得分:2)
似乎你必须恢复变异,因为你不能有新的实例和行为必须改变。这可能是最简单的选项(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
答案 1 :(得分:1)
这在JVM上是不可能的 - 无论是Java还是Scala - 都不是你所要求的。
参见例如In Java, given an object, is it possible to override one of the methods?
使用Scala而不是Java不会获得额外的杠杆作用,因为类和方法在Scala中的工作原理基本与Java相同。 (这是出于性能和互操作的原因。)