在Scala

时间:2015-09-14 19:31:48

标签: scala

有没有办法在所有对象之间共享变量(从同一类型实例化)?考虑以下简单程序。两个对象namename2具有相同的类型A。有没有办法连接两个实例properyListname中的name2

class A {
  var properyList = List[String]()
  def printProperties(): Unit = {
    println(properyList)
  }
}

object Experiment {
  def main(args: Array[String]): Unit = {
    val name = new A
    val name2 = new A
    name.properyList = List("a property")
    name.printProperties()
    name2.printProperties()
  }
}

输出

List(a property)
List()

任何更改类定义的方法,只需更改其中一个对象中的.properyList,它就会在所有实例中更改?

4 个答案:

答案 0 :(得分:9)

你似乎在寻找的是一个类变量。在我开始讨论为什么你应该避免这种情况之前,让我解释一下你可以做什么:

您可以将propertyList附加到随播对象而不是类:

object A {
  var properyList = List[String]()
}

class A {
  def printProperties(): Unit = {
    println(A.properyList)
  }
}

现在,为什么你不应该

虽然 scala 让你做几乎JVM能够做的任何事情,但它的目的是鼓励一种函数式编程风格,它通常避开可变状态,特别是共享,可变状态。即A中的反模式不仅是propertyList是var,而不是val,而是通过伴侣对象共享它,你进一步允许任何人从任何线程更改任何时候所有实例的状态。

将您的数据声明为val的好处是,您可以放心地传递它,因为您可以确定将来任何时候都无法改变您的身份。

答案 1 :(得分:4)

您似乎在寻找类似java静态字段的内容。

在scala中,你通常可以通过使用伴侣对象来实现类似的东西:

object Main extends App {
  class A {
    import A._

    def printProperties(): Unit = {
      println(properyList)
    }
  }

  object A {
    private var properyList = List[String]()

    def addProperty(prop: String): Unit = {
      properyList ::= prop
    }
  }


  val name = new A
  val name2 = new A
  A.addProperty("a property")
  name.printProperties()
  name2.printProperties()
}

答案 2 :(得分:2)

如果你想要类似于java的静态字段,你将不得不使用伴侣对象。

Traceback (most recent call last):
  File "C:/Python34/Gw2.py", line 6, in <module>
    htmlfile = urlopen("http://xiv-market.com/item_details.php?id=2727")
  File "C:\Python34\lib\urllib\request.py", line 153, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python34\lib\urllib\request.py", line 461, in open
    response = meth(req, response)
  File "C:\Python34\lib\urllib\request.py", line 574, in http_response
    'http', request, response, code, msg, hdrs)
  File "C:\Python34\lib\urllib\request.py", line 499, in error
    return self._call_chain(*args)
  File "C:\Python34\lib\urllib\request.py", line 433, in _call_chain
    result = func(*args)
  File "C:\Python34\lib\urllib\request.py", line 582, in http_error_default
    raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 403: Forbidden

代码复制自: "Static" field in Scala companion object

http://daily-scala.blogspot.com/2009/09/companion-object.html

答案 3 :(得分:0)

基于Arne Claassen的回答,但是使用私有的可变集合和伴随对象,这使得它只对伴侣类可见。在scala 2.11.7控制台中尝试了非常简单的示例:

scala> :paste
// Entering paste mode (ctrl-D to finish)

object A {
   private val mp = scala.collection.mutable.Map("a"->1)
}

class A {
def addToMap(key:String, value:Int) = { A.mp += (key -> value) }
def getValue(key:String) = A.mp.get(key)
}

// Exiting paste mode, now interpreting.

defined object A
defined class A

// create a class instance, verify it can access private map in object
scala> val a = new A
a: A = A@6fddee1d

scala> a.getValue("a")
res1: Option[Int] = Some(1)

// create another instance and use it to change the map
scala> val b = new A
b: A = A@5e36f335

scala> b.addToMap("b", 2)
res2: scala.collection.mutable.Map[String,Int] = Map(b -> 2, a -> 1)

// verify that we cannot access the map directly
scala> A.mp // this will fail
<console>:12: error: value mp is not a member of object A
       A.mp
         ^
// verify that the previously created instance sees the updated map
scala> a.getValue("b")
res4: Option[Int] = Some(2)