首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何存储方法而不在每次方法调用时重新创建它们

如何存储方法而不在每次方法调用时重新创建它们
EN

Stack Overflow用户
提问于 2014-11-10 05:52:05
回答 3查看 139关注 0票数 3

我有一个Scala类,它的方法使用了很多正则表达式。每个类方法都使用一些正则表达式模式。从代码模块化的角度来看,我应该将这些模式存储在method中:

代码语言:javascript
运行
复制
class Bar {
    def foo() {
        val patt1 = "[ab]+".r
        val patt2 = "[cd]+".r
        /*...*/
    }
}

但是这种方法的效率非常低。在每次方法调用时都会重新编译模式。我可以直接把它们移到课堂上:

代码语言:javascript
运行
复制
class Bar {
    val fooPatt1 = "[ab]+".r
    val fooPatt2 = "[cd]+".r
    /*...*/
}

但是,当我有30个方法时,它看起来很丑陋。

我最终得到了一些使用val和匿名函数的混合解决方案:

代码语言:javascript
运行
复制
val z = {
    val patt1 = "[ab]+".r
    val patt2 = "[cd]+".r
    () => { /* ... */ }
}

但我不确定使用val存储函数与使用def相比是否有一些缺点。也许有其他干净的解决方案来存储方法常量而不污染类?

EN

回答 3

Stack Overflow用户

发布于 2014-11-10 06:14:24

使用val是非常好的。可能会有(非常)小的性能影响,但在大多数(99.9%)的应用程序中,这不是问题。

还可以为该方法创建一个类

代码语言:javascript
运行
复制
// 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() = {
    ...
  }
}

然后在课堂上:

代码语言:javascript
运行
复制
class Bar {
  val foo = new Foo
}

另一种解决方案是使用特征

代码语言:javascript
运行
复制
trait Foo {
  private lazy val patt1 = "[ab]+".r
  private lazy val patt2 = "[cd]+".r

  def foo() = ...
}

class Bar extends Foo with ...

请注意,如果您在单个类中有类似的不同方法,则可能表明违反了单一责任原则。将它们移到自己的类(或特征)也可以解决这个问题。

票数 2
EN

Stack Overflow用户

发布于 2014-11-10 15:27:34

我会将每个具有必要正则表达式的方法放在它自己的特征中:

代码语言:javascript
运行
复制
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)
}

要测试的

  • clean
  • separated
  • easy (object AMethodSpec使用AMethod扩展属性(“AMethod”) ...)
票数 2
EN

Stack Overflow用户

发布于 2014-11-11 04:48:52

我考虑到了Chris的评论。将模式放到伴生对象中可能是最有效的方法,但当我们有更多的方法时,这是非常不干净的。EECOLOR解决方案效率较低,但更干净。特征防止在每次方法调用时重新创建模式。不幸的是,scala没有在多个类实例中使用相同的编译模式:

代码语言:javascript
运行
复制
(new X).patt1==(new X).patt1 // would be false.

我将这两种方法结合起来,并使用对象来代替特征。

代码语言:javascript
运行
复制
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应该为这个问题提供一些开箱即用的解决方案。模式是最简单的例子。我们可以有其他不可变的对象,这些对象的初始化开销要大得多。在外部某处提取方法的内部细节仍然不清楚。如果能像懒惰人一样做这件事,那就太好了。添加一个修饰符应该确保值在所有实例和方法调用中仅为实例一次。应该是这样的:

代码语言:javascript
运行
复制
def method1 {
 static val  x = new VeryExpensiveObject
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26833737

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档