Make42 Make42 - 1 month ago 20
Scala Question

Scala Functions as object vs class

trait MyFunctionTrait extends ((Int, Int) => Double)

class MyFunction1 extends MyFunctionTrait {
override def apply(a: Int, b: Int) => Double = a/b
}

object MyFunction2 extends MyFunctionTrait {
override def apply(a: Int, b: Int) => Double = a/b
}


I am not entirely sure which one to use how. Is the differency how to run them?

scala> val f = new MyFunction1
f: MyFunction1 = <function2>

scala> f(1,2)
res50: Double = 0.0

scala> MyFunction2(1,2)
res48: Double = 0.0


I do know what the difference between a singleton object and a class is. I want to know the use-cases in the particular case of defining a Function. A Function is explained in articles, but I have seen it programmed as a class and as an object, so I'd like to know what best practise is when and why.

In my particular case I want to give another Function as a parameter to the Function in a currying style and then have different
MyFunction
which do slightly different stuff depending on what Function they got: How to write a currying Scala Function trait?

Please answer for 1) the general case, 2) the particular case.

PS: I tried to separate the question on how to curry and whether class or object - did not seem to work so well, right here.

Answer

It depends on what you are trying to do!


The apply() function in scala is just syntactic sugar [1, 2], which allows you to use MyObject(x) as a shorthand for MyObject.apply(x).

An object in scala is a singleton, which means there will at most be exactly one instance of the class. Hence, you can call MyFunction2(1,2).

A class is a type with known fields and functions. It is a definition of what you're trying to model with your code. Hence, you cannot call MyFunction1(1,2), as you need an instance of the class to be able to access its fields and functions.


That being said, you might want to rethink what you are trying to do. Classes and Objects are not - in that sense - simple mathematical functions, where you define object x, object y, ..., and then use x(...) and y(...). What you would want to create is either a class or an object (i.e. singleton class) where you define your functions, e.g.

object Calculator {

    def add(a: Int, b:Int): Int = {
        return a + b
    }

    def subtract(a: Int, b: Int): Int = {
        return a - b
    }

}

which you can then use to call your functions, e.g. Calculator.add(2,3).

or

class Calculator {

    def add(a: Int, b: Int): Int = {
       return a + b
    }
}

which you would use likewise

val calc = new Calculator
calc.add(3,2)

Again, you will find that you can use object Calculator without creating an instance. You could compare fields and parameters defined in a Scala object with static fields in a Java class, which you can also access without creating an instantiating an object of the class. Which one you should is entirely depends on what you are trying to program. To find out, you may want to read Difference between object and class in Scala

Comments