Daniel
Daniel

Reputation: 6039

Sharing variables among objects in Scala

Is there a way to share a variable among all objects (instantiated from the same type)? Consider the following simple program. Two objects name and name2 have the same type A. Is there way to connect the properyList inside the two instantiation name and 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()
  }
}

The output is

List(a property)
List()

Any way to change the class definition so that by just changing the .properyList in one of the objects, it is changed in all of the instatiations?

Upvotes: 4

Views: 4376

Answers (4)

Arne Claassen
Arne Claassen

Reputation: 14404

What you seem to be looking for is a class variable. Before I get into why you should avoid this, let me explain how you can do it:

You can attach propertyList to the companion object instead of the class:

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

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

Now, to the why you shouldn't:

While scala let's you do pretty much anything that the JVM is capable of, its aims are to encourage a functional programming style, which generally eschews mutable state, especially shared, mutable state. I.e. the anti-pattern in A is not only that propertyList is a var, not a val but by sharing it via the companion object, you further allow anyone, from any thread to change the state of all instances at anytime.

The benefit of declaring your data as val is that you can safely pass it around, since you can be sure that nobody can change from under you at any time in the future.

Upvotes: 10

Ashalynd
Ashalynd

Reputation: 12563

Based on Arne Claassen's answer, but using private mutable collection with the companion object, which makes it visible only to the companion classes. Very simplistic example tried out in scala 2.11.7 console:

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)

Upvotes: 0

Sascha Kolberg
Sascha Kolberg

Reputation: 7152

You seem to be looking for something like java static fields.

In scala you usually achieve something like that by using a companion object:

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()
}

Upvotes: 4

Haito
Haito

Reputation: 2069

If you want to have something similar to java's static fields you will have to use companion objects.

    object Foo {
        private var counter = 0
        private def increment = {
           counter += 1; 
           counter
        }
    }

    class Foo {
        val i = Foo.increment
        println(i)
    }

Code copied from: "Static" field in Scala companion object

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

Upvotes: 2

Related Questions