我有Scala类,哪些方法使用了很多正则表达式。每个类方法都使用一些正则表达式模式。 从代码模块化的角度来看,我应该将这些模式存储在方法中:
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相比是否有一些缺点。也许还有其他干净的解决方案来存储方法常量而不会污染类?
答案 0 :(得分:2)
使用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 ...
请注意,如果您在单个班级中使用不同的方法,则可能表示违反了单一责任原则。将它们移动到自己的类(或特征)也可以解决该问题。
答案 1 :(得分:2)
我会在每个方法中都使用必要的正则表达式自己的特性:
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)
}
答案 2 :(得分:0)
我考虑了克里斯的评论。将模式放到伴侣对象可能是最有效的方法,但是当我们有更多方法时非常不洁净。 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应该为开箱即用的问题提供一些解决方案。模式是最简单的例子。我们可以有其他不可变对象,初始化要贵得多。 在外面某处提取方法内部仍然不清楚。与懒惰的vals一样,这样做会很好。添加一个修改器应该确保所有实例和方法调用中的值只是实例一次。它会是这样的:
def method1 {
static val x = new VeryExpensiveObject
}