1

我正在寻找很长一段时间来解决以下问题:我的类“B”的每个实例都使用一种方法将 Seq“输出”存储在文件中。

class B extends IO {
    private var b = 0.0
    var output = Seq(0.0)

    def add(a:Int) = {
        b += a
        output :+= b
        WriteToFile(fileName, output)
    }
}

WriteToFile 方法还有一个特点:

trait IO {
    def WriteToFile(fileName:String, data:Seq[Int]) = {
        create file and name it something like: fileName+this+".m"
    }
}

因此,每次在类“B”的实例上调用方法“add”时,输出序列都会存储在文件中。我想为“B”类的每个实例创建一个不同的文件。但是当我创建一个实例时

val x = new B

WriteToFile 方法中的 this 关键字只是将“Bank()”添加到文件名中。那么,如何更改代码以使“B”类的每个新实例都创建自己的文件呢?以及如何更改 WriteToFile-Method 以将实例名称(此处为“x”)添加到确定文件名的字符串中?

4

2 回答 2

2

我不鼓励您尝试根据变量的名称来命名对象实例。变量与引用非常不同。例如,让我们有这段代码:

def foo: Object = {
    val x = new Object;
    val y = x;
    return x;
}

此方法创建一些新的Object. 对对象的引用被分配给变量x,然后被分配给变量y。所以现在我们有一个对象,但被两个变量引用。当方法返回时,对象仍然存在,但可能有变量引用它。

因此,通过持有它的变量来命名对象并不是很有意义 - 可以有多个这样的变量,或者没有,并且它在对象的生命周期内会发生变化。

相反,我建议您创建自己的机制来生成名称。一种可能性是使用原子计数器(以便可以从多个线程安全地使用它):

trait AtomicName {
  val name = "prefix" + AtomicName.newId;
}
object AtomicName extends App {
  import java.util.concurrent.atomic.AtomicInteger;

  private val counter = new AtomicInteger(0);

  protected def newId = counter.getAndIncrement;
}

现在所有扩展AtomicName都将有一个唯一的名称。

于 2013-07-11T13:18:31.417 回答
1
trait IO {
  def myName = 
    this.getClass.getName.split("\\$",-1).dropRight(1).lastOption.getOrElse("")
}

class B extends IO {
  var output = Seq(0.0)
}

object x extends B {
  def test { println(myName + " has " + output) }
}

请注意,您必须使用object x而不是val x,这确实包含一些开销,而且它是惰性的——x在第一次使用它的内容时创建,而不是第一次声明它。(如果你调用myName不是对象的东西,它会给你一个空字符串。)

我认为这是一个坏主意,但这是如何做到的。

于 2013-07-11T15:56:16.957 回答