Scala:在运行时替换方法
Scala: replace method at runtime
假设我有一个 class
class Original {
def originalMethod = 1
}
现在,假设我有一个实例
val instance = new Original
现在是否可以在运行时对 instance
做一些事情来用不同的方法替换 originalMethod
? (假设签名保持不变)
例如,现在调用instance.originalMethod
时会调用下面的代码println("test"); 1
编辑
我不能打电话给 new Original
。我只有它的现有实例,我必须对其进行修改。
编辑 2
(@Aleksey Izmailov 的回答)这是一个很好的解决方案,但并不是我想要的。我在测试方面考虑更多 - 编写 class "normally",而不是将函数指定为变量而不是方法
PS。我在尝试模仿 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
有趣的是,您无法使用此 class 的通用版本进行默认实现,因为除非您将其更改为 Unit
或部分功能,否则您无法使用默认值。
这是它的通用版本:
scala> class Original[T] {
| var originalMethod: () => T = null
| }
defined class Original
scala> val genImpl = new Original[Int] { originalMethod = () => 111 }
genImpl: Original[Int] = $anon@6b04acb2
scala> genImpl.originalMethod()
res8: Int = 111
scala> genImpl.originalMethod = () => 222
genImpl.originalMethod: () => Int = <function0>
scala> genImpl.originalMethod()
res9: Int = 222
这在 JVM 上是不可能的 — 在 Java 或 Scala 中 — 不是您要求的方式。
参见例如In Java, given an object, is it possible to override one of the methods?
使用 Scala 而不是 Java 不会让您获得额外的优势,因为 类 和方法在 Scala 中的工作原理与 Java 相同。 (这样做是出于性能和互操作的原因。)
假设我有一个 class
class Original {
def originalMethod = 1
}
现在,假设我有一个实例
val instance = new Original
现在是否可以在运行时对 instance
做一些事情来用不同的方法替换 originalMethod
? (假设签名保持不变)
例如,现在调用instance.originalMethod
时会调用下面的代码println("test"); 1
编辑
我不能打电话给 new Original
。我只有它的现有实例,我必须对其进行修改。
编辑 2 (@Aleksey Izmailov 的回答)这是一个很好的解决方案,但并不是我想要的。我在测试方面考虑更多 - 编写 class "normally",而不是将函数指定为变量而不是方法
PS。我在尝试模仿 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
有趣的是,您无法使用此 class 的通用版本进行默认实现,因为除非您将其更改为 Unit
或部分功能,否则您无法使用默认值。
这是它的通用版本:
scala> class Original[T] {
| var originalMethod: () => T = null
| }
defined class Original
scala> val genImpl = new Original[Int] { originalMethod = () => 111 }
genImpl: Original[Int] = $anon@6b04acb2
scala> genImpl.originalMethod()
res8: Int = 111
scala> genImpl.originalMethod = () => 222
genImpl.originalMethod: () => Int = <function0>
scala> genImpl.originalMethod()
res9: Int = 222
这在 JVM 上是不可能的 — 在 Java 或 Scala 中 — 不是您要求的方式。
参见例如In Java, given an object, is it possible to override one of the methods?
使用 Scala 而不是 Java 不会让您获得额外的优势,因为 类 和方法在 Scala 中的工作原理与 Java 相同。 (这样做是出于性能和互操作的原因。)