我有一个第三方类,我不能修改。我想添加一个透明的retry
功能。因此调用者不知道重试正在幕后进行。我遇到过两种第三方类。一个是我可以扩展的,另一个是不能扩展的(私有或受保护的)。对于我不能扩展的一个,这里是我的解决方案:
class 3rdPartyClassA {
def doSomething()
}
class MyAppClassA {
val 3rdpartyobjA = new 3rdPartyClassA()
def doSomething() {
Retry.retry(3rdpartyobjA.doSomething()) //wrapping 3rdparty call with retry
}
}
object ClientFactory {
def get3rdPartyclassA() = new MyAppClassA
}
class CallerCode {
ClientFactory.get3rdPartyclassA().doSomething() //doSomething is called with Retry
}
在上面的解决方案中,我必须为3rdPartyClassA
中的每个方法创建一个包装器方法。即使我可以扩展3rdPartyClassA
,我也必须重写每个方法来添加Retry
逻辑。有没有办法避免这种情况?像运行时一样,我可以说这个类的每个方法调用都应该包含在我的Retry
逻辑中。如果是这样,该解决方案的缺点是什么?
发布于 2021-02-07 08:22:21
对于这个问题没有直接的解决方案。您可以使用Dynamic
特征并使用反射调用底层对象的方法。https://www.scala-lang.org/api/current/scala/Dynamic.html但是,如果你这样做,类型安全就会被抛在脑后,这不仅会导致错误,还会降低性能,使IDE变得无用。我宁愿接受包装样板,也不愿采用这种方法。
您还可以使用宏实现selectDynamic
,这至少可以恢复类型安全。但这也不是一个好主意,因为当前形式的宏在Scala3中消失了,这是有充分理由的。
另一种可能是编写一个源代码生成器,它将使用反射生成样板。下面是关于如何将其与sbt:https://www.scala-sbt.org/1.x/docs/Howto-Generating-Files.html集成的一些信息,但除非包装类的API非常大,否则可能更快的方法是咬住子弹,手工编写样板文件。
https://stackoverflow.com/questions/66069525
复制相似问题