5

I have a doubt about what is the difference between this two pieces of code.

The obvious ones are that if the method is written in the class you must instantiate the class, while if it is in the companion object, you are not required to do that.

However, Are there also other differences? Which are the benefits and drawbacks?

define a method in the class

class Hello {
  def hello = println("Hello world")
}

object Hello {
  def main(args: Array[String]) {
    val instance = new Hello()
    instance.hello
  }
}

define a method in the companion object

class Hello {

}

object Hello {

  def hello = println("Hello world")

  def main(args: Array[String]) {
    this.hello
  }
}
agusgambina
  • 6,229
  • 14
  • 54
  • 94
  • 3
    One difference: objects, and their methods, cannot be inherited or overridden. – jwvh Nov 17 '16 at 02:00
  • 3
    Methods are not allocated when a class is instantiated, so there is no duplication here. You still need to allocate memory for an instance itself. – Victor Moroz Nov 17 '16 at 04:25
  • @VictorMoroz thank you, my bad, I will edit the question, from the Odersky book `the runtime sets aside some memory to hold the image of that object's state` that means that the allocation is only for the fields – agusgambina Nov 17 '16 at 22:36
  • @jwvh I learned that today, from you. Thanks. Have never in my 5 years with Scala realized I cannot inherit from an Object. – akauppi Jun 13 '17 at 16:47

1 Answers1

7

If you remember that Scala came from Java, it may make a bit more sense. In Java, there's only a class, and it has static methods, which do not depend on any fields in an instance (but can read static fields) and regular (non-static, instance-level) methods. The distinction is between "functionality that is common to SomeType but to no instance in particular", and "functionality that needs the state of a particular instance". The former are static methods in Java, and the latter are instance methods. In Scala, all the static parts should go in the object, with the instance-level val and def being in the class. For example:

object MyNumber {
    // This does not depend on any instance of MyNumber
    def add(c: Int, b: Int): Int = c + b
}
class MyNumber(a: Int) {
    // This depends on an instance of MyNumber
    def next: Int = a + 1
}
radumanolescu
  • 4,059
  • 2
  • 31
  • 44
  • 3
    This. In fact, IMHO it's a best practice to always keep a lookout for class members which don't actually use instance members, and move them to the static companion object. – Yawar Nov 17 '16 at 02:09
  • 1
    @Yawar Unless you want to override them in a subclass, check e.g. type class pattern. – Victor Moroz Nov 17 '16 at 04:21
  • @VictorMoroz, I think in these patterns it's a priori understood that we have to do things in a certain way. Still, good point though. – Yawar Nov 17 '16 at 04:33
  • @Yawar Even though a method doesn't touch instance members, it doesn't always make sense from the design perspective to put it inside an `object`. To each case his own, I wouldn't take that as a "rule of thumb". – Yuval Itzchakov Nov 17 '16 at 07:02
  • @radumanolescu thank you for your answer. If I had understood well, I would have changed the letter "a" of the method of the object for another letter because is not related with the member of the class. – agusgambina Nov 17 '16 at 12:19
  • 1
    @agusgambina I have edited the example to remove any connection between the names. The compiler was never confused, though. One was a method parameter and the other was a class member. – radumanolescu Nov 17 '16 at 13:15