Erdi İzgi Erdi İzgi - 1 month ago 6
Scala Question

Creating Singleton Object from a class in Scala

When I was playing with the Scala, I couldn't figure out something. Maybe I am doing completely wrong.

I was trying with Rational Example and Complex Example but I couldn't find a way to use operations like R*3/5 and 1/2*R

here is the complex numbers example I am working on

class Complex(val real : Int, val img : Int){

def this(real: Int) = this(real, 0)

def *(that : Complex) = {
val realPart = this.real * that.real + -(this.img * that.img)
val imgPart = this.real * that.img + this.img * that.real
new Complex(realPart, imgPart)
}

override def toString = this.real + "+" + this.img + "i"

}

object Complex {
def apply(real : Int, img : Int) = new Complex(real, img)
def apply(real : Int) = new Complex(real)
}

object ComplexNumbers {

def main(args: Array[String]) {

import ComplexConversions._
println(Complex(1,2)) // 1+2i
println(I*2) //0+2i
println(2*I) //0+2i
}
}


Well I have tried to create an object I

object I{
def apply() = new Complex(0,1)

def *(that : Complex) = {
val realPart = 0 * that.real + -(1 * that.img)
val imgPart = 0 * that.img + 1 * that.real
new Complex(realPart, imgPart)
}
}


but it did work for the I*2. but I have problems for 2*I. How can I reach the result that I want?

Answer

When you call "I * 2", scala looks for a method named "*" on the class of I, and finds it.

When you call "2 * I", scala looks for a method named "*" on the class of 2 (which is Int), and cannot find one.

Even though Int is defined externally, you can add this method to it in Scala via the "implicit conversion" mechanism. This is covered briefly in the "implicits" example and in more detail elsewhere, e.g. here

Try adding some code like the following to your "Complex" object:

object Complex {
  implicit class IntOps(x: Int) {
    def *(y: Complex) = y * x
  }
}

You'll also need to declare I as a val, rather than an Object for this to work:

val I = Complex(0, 1)

(or add an implicit method like class Complex { def *(i: I) = ... }, but that's much uglier)

(I assume by Complex Example, you mean this?)


Working code:

class Complex(val real : Int, val img : Int){

  def this(real: Int) = this(real, 0)

  def *(that : Complex) = {
    val realPart = this.real * that.real + -(this.img * that.img)
    val imgPart = this.real * that.img + this.img * that.real
    new Complex(realPart, imgPart)
  }

  override def toString = this.real  + "+" + this.img + "i"

}

object Complex {
  def apply(real : Int, img : Int) = new Complex(real, img)
  def apply(real : Int) = new Complex(real)

  val I = Complex(0, 1)

  implicit def toComplex(x: Int): Complex = new Complex(x)
}

object ComplexNumbers {

  def main(args: Array[String]) {

    import Complex._

    println(Complex(1,2)) // 1+2i
    println(I*2) //0+2i
    println(2*I) //0+2i
  }
}
Comments