简体   繁体   English

Scala-单例对象继承

[英]Scala - Singleton Object inheritance

I have a working Scala application in production that is using a object which has several methods defined inside it. 我在生产中有一个运行中的Scala应用程序,它使用的object内部定义了几种方法。

There are new requirements for this application where I will have to rewrite (override) few of the methods from that object while reusing the definitions of remaining methods from that object . 有此应用程序,我将不得不重写(覆盖)几个从该方法的新需求object ,而重复使用的从其余的方法定义object

How can I create a new object inheriting the original one so that I can override the definitions of a few selected methods? 如何创建一个继承原始object的新object ,以便覆盖某些选定方法的定义?

A Scala object cannot inherit from another Scala object so the obvious way is not possible. 一个Scala object不能从另一个Scala object继承,因此不可能采用明显的方式。

If you can modify the original object then create a class that implements all the functionality and make the original object inherit from that class. 如果可以修改原始object则创建一个实现所有功能的类,并使原始object继承自该类。 Your new object can then inherit from the same class and override the methods that you want to change. 然后,新对象可以从相同的类继承,并覆盖您要更改的方法。 However this will create two copies of any values in the base class, so it is not suitable for an object that contains a lot of data or does any one-off initialisation. 然而,这将创建在基类的任何值的两个副本,因此它是不适合的object ,其中包含大量的数据或是否有任何一次性的初始化。

If you cannot modify the original object then you will have to copy all the methods of the first object in your new object . 如果无法修改原始object则必须在新object复制第一个object所有方法。 val s can be copied directly. val可以直接复制。 defs can be copied using eta expansion: defs可使用ETA扩张复制:

def v = Original.v    // This is a simple value
def f = Original.f _  // This is a function value

Using def rather than val here will avoid storing multiple copies of the original values and will prevent lazy values from being computed until they are needed. 在这里使用def而不是val将避免存储原始值的多个副本,并且将防止在需要之前计算惰性值。

Using eta expansion will make f a function value rather than a method which may or may not be a problem depending on how it is used. 使用eta扩展将使f成为函数值,而不是使方法成问题的方法,具体取决于如何使用它。 If you require f to be a method then you will have to duplicate the function signature and call the original f: 如果要求f为方法,则必须复制函数签名并调用原始f:

def f(i: Int) = Original.f(i) // This is a method

My suggestion would be to move the code/logic to a trait or abstract class and have both objects extend these. 我的建议是将代码/逻辑移至traitabstract class并让两个objects都对它们进行扩展。

On the upside this would also give you better testability. 从好的方面来说,这也将为您提供更好的可测试性。

Another more hacky approach could be to not use the class/type system at all and jsut forward the methods using a new singleton objec: 另一个更棘手的方法可能是根本不使用类/类型系统,而是使用新的单例objec来转发方法:

scala> object A {def foo: String = "foo" ; def bar:Int = 0}
defined object A

scala> object B { def foo = A.foo; def bar = "my new impl" }
defined object B

scala> A.foo
res3: String = foo

scala> B.foo
res4: String = foo

scala> A.bar
res5: Int = 0

scala> B.bar
res6: String = my new impl

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM