USER
USER

Reputation: 77

Singleton Object vs Companion Object in Class

I have written the following code:

class a {

  object c {
    var a = "STATIC"

    def m() = print("STATIC METHOD")

    var f = () => print("STATIC FUNCTION")
  }

}

object m {
  def main(args: Array[String]) = {
    var o = new a()
    o.c.m()
  }
}
  1. Can I say that the variables, functions and methods that are declared in object c can be static?
  2. If I change name of object c with a then will the object becomes a companion object?

Upvotes: 3

Views: 532

Answers (3)

stefanobaghino
stefanobaghino

Reputation: 12794

Fields and methods in an object are how Scala declares things that you would have used static for in Java. I guess you can, for intuition sake, say that those fields are usually static (as in only one of those in a JVM at once).

However, in your example, you put an object inside a class, making it no longer static. You can easily check this with a few lines of code (that you can find here on Scastie).

class MyClass {

  object Embedded {
    val a = "field"
    def m = println("method")
  }

}

val a = new MyClass().Embedded
val b = new MyClass().Embedded

// prints "a and b are different objects"
if (a eq b)
  println("a and b are the same object")
else  
  println("a and b are different objects")

Regarding your second question: no, class and object must be in the same scope in order for it to be a companion object. You can find more details on the Scala Language Specification.

I quote from there:

Generally, a companion module of a class is an object which has the same name as the class and is defined in the same scope and compilation unit. Conversely, the class is called the companion class of the module.

Upvotes: 3

FurryMachine
FurryMachine

Reputation: 1698

To answer you questions:

  1. The methods and fields in a.c are not globally static because they need an instance of a to exist. If a were an object, a.c would be static too.

  2. If you want to have a companion object with static fields and methods for your class a it has to be defined outside of a's code block, like this:

    class a {
      /* non-static stuff goes here */
    }
    object a {
      /* static stuff goes there */
      def m() = print("STATIC METHOD")
    }
    

You must keep both in the same file, defining the object or the class first doesn't matter, so it generally depend on a convention or what makes most sense depending on use case. If you want to call the static method a.m inside the class a, you will still need to call it a.m and not just m. But the class a will be able to use private fields and methods of object a, because they are companions.

As others already said, static doesn't really exist in Scala, but the concept transpires from Java since Scala is in most cases compiled into java bytecode.

Last advice, the convention is usually the same in Scala and in Java for classes and object: the first-letter of their name should be uppercase (except in some advanced Scala cases)

Upvotes: 2

Ryan Leach
Ryan Leach

Reputation: 4470

Scala has no true meaning of 'static' that Java does.

The fact that objects have a backing on the JVM that uses static methods / fields is a leaking implementation detail that you only need to deal with if using Java/JVM interop.

Unless you explicitly need that interop, you need to stop thinking of declared objects as 'static' and instead think of them as singletons within their given scope.

An inner object nested under a class, means that there is only ever going to be 1 instance of that object, for each class instance, unlike inner classes which could have multiple instances.

This applies at the top level as well, except that Scala can do additional compatibility with other JVM languages, and mark some of the methods/members as static.

Upvotes: 3

Related Questions