我有一个Scala类,它的方法使用了很多正则表达式。每个类方法都使用一些正则表达式模式。从代码模块化的角度来看,我应该将这些模式存储在method中:
class Bar {
def foo() {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
/*...*/
}
}
但是这种方法的效率非常低。在每次方法调用时都会重新编译模式。我可以直接把它们移到课堂上:
class Bar {
val fooPatt1 = "[ab]+".r
val fooPatt2 = "[cd]+".r
/*...*/
}
但是,当我有30个方法时,它看起来很丑陋。
我最终得到了一些使用val和匿名函数的混合解决方案:
val z = {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
() => { /* ... */ }
}
但我不确定使用val存储函数与使用def相比是否有一些缺点。也许有其他干净的解决方案来存储方法常量而不污染类?
发布于 2014-11-10 06:14:24
使用val
是非常好的。可能会有(非常)小的性能影响,但在大多数(99.9%)的应用程序中,这不是问题。
还可以为该方法创建一个类
// The extends is not needed, although you might want to hide the Foo type
class Foo extends (() => ...) {
val patt1 = "[ab]+".r
val patt2 = "[cd]+".r
def apply() = {
...
}
}
然后在课堂上:
class Bar {
val foo = new Foo
}
另一种解决方案是使用特征
trait Foo {
private lazy val patt1 = "[ab]+".r
private lazy val patt2 = "[cd]+".r
def foo() = ...
}
class Bar extends Foo with ...
请注意,如果您在单个类中有类似的不同方法,则可能表明违反了单一责任原则。将它们移到自己的类(或特征)也可以解决这个问题。
发布于 2014-11-10 15:27:34
我会将每个具有必要正则表达式的方法放在它自己的特征中:
class Bar extends AMethod with BMethod
trait AMethod {
private val aPattern = """\d+""".r
def aMethod(s: String) = aPattern.findFirstIn(s)
}
trait BMethod {
private val bPattern = """\w+""".r
def bMethod(s: String) = bPattern.findFirstIn(s)
}
要测试的
发布于 2014-11-11 04:48:52
我考虑到了Chris的评论。将模式放到伴生对象中可能是最有效的方法,但当我们有更多的方法时,这是非常不干净的。EECOLOR解决方案效率较低,但更干净。特征防止在每次方法调用时重新创建模式。不幸的是,scala没有在多个类实例中使用相同的编译模式:
(new X).patt1==(new X).patt1 // would be false.
我将这两种方法结合起来,并使用对象来代替特征。
object X {
object method1 {
val patt1 = "a".r
}
object method2 {
val patt1 = "a".r
}
}
class X {
def method1 = {
import X.method1._
patt1
}
def method2 = {
import X.method2._
patt1
}
}
(new X).method1 == (new X).method1 // true
(new X).method2 == (new X).method2 // true
虽然这种方法有效,但我认为scala应该为这个问题提供一些开箱即用的解决方案。模式是最简单的例子。我们可以有其他不可变的对象,这些对象的初始化开销要大得多。在外部某处提取方法的内部细节仍然不清楚。如果能像懒惰人一样做这件事,那就太好了。添加一个修饰符应该确保值在所有实例和方法调用中仅为实例一次。应该是这样的:
def method1 {
static val x = new VeryExpensiveObject
}
https://stackoverflow.com/questions/26833737
复制相似问题