0

Does Scala have implicit conversions for objects? For example, if I have a method with the following signature:

object Foo {
  def print(message: String) = println(message)
}

class Bar {
    val baz = 1
}

How can I call Foo.print(new Bar)?

Can I put a method on the Bar class to implicitly convert Bar instance to a string without having to call toString in the argument?

C# has this and I'm wondering if scala does too.

Let's say we have Scala enum:

object Color extends Enumeration {

  type Method = Value

  val RED, BLUE, GREEN = Value

 }

Then I have a class:

object ColorPrinter {
  def print(x: String) = {
    println(x)
  }
}

ColorPrinter's print method can't be changed.

I want to call into ColorPrinter.print(Color.RED), but I can't do that. I would have to call it like this: ColorPrinter.print(Color.RED.toString).

I want to avoid having to toString

Ryan McCullagh
  • 13,581
  • 8
  • 56
  • 101

3 Answers3

2

Converting things implicitly to basic types, like String or Int isn't really a very good idea (the implicit conversion may trigger in places where you do not expect it to, creating subtle, hard to debug, issues).

Why not just make it explicit? ?

class Bar {
   val baz = 1
   def print = Foo.print(toString)
}

new Bar().print
Dima
  • 33,157
  • 5
  • 34
  • 54
2

You can put implicit conversions that can be applied automatically without importing into the companion object of the class:

class Bar {
  val baz = 1
}

// This should be the companion object of `Bar`, so if in console, use :paste mode
object Bar {
  implicit def toString(bar: Bar): String = bar.toString
}

scala> Foo.print(new Bar) // works without `import Bar._`
$line7.$read$$iw$$iw$Bar@280ecc33

For Enumerations you can put conversions into the object itself:

object Color extends Enumeration {

  type Method = Value

  val RED, BLUE, GREEN = Value

  implicit def toString(value: Value): String = value.toString 
}

scala> ColorPrinter.print(Color.RED) // works without `import Color._`
RED

You can read more about implicit resolution in Scala in this answer: https://stackoverflow.com/a/5598107/1098230

Kolmar
  • 13,241
  • 1
  • 19
  • 24
1

Here is a typical approach, yes, Implicit's very similar to C# static methods and its implemented in adhoc way:

object Foo {
  def print(message: String) = println(message)
}

class Bar {
  val baz = 1
}

object BarToStringMaker {
   implicit def barToString(b : Bar) : String = b.baz.toString
}

import BarToStringMaker._

Foo.print(new Bar)

more reading:

http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html

hope that helps,

HTNW
  • 22,326
  • 1
  • 24
  • 53
Pavel
  • 1,475
  • 20
  • 28
  • 1
    I don't think implicits had C# static methods in mind: https://softwareengineering.stackexchange.com/questions/150953/historical-origins-of-scala-implicits and https://stackoverflow.com/questions/3069432/other-programming-languages-that-support-implicits-a-la-scala. – pedrofurla Jun 28 '17 at 16:00
  • agree, possibly misinterpreted what was written in the book, its was not a response to C# changes, updated my answer. – Pavel Jun 28 '17 at 16:03
  • 1
    Implicits defined in the companion object don't need explicit importing. Converting to a string is a really bad idea.The print method is no different than println. – flavian Jun 28 '17 at 16:10
  • @flavian the print method is just a complexity reduction. My use case is more complex than a a simple wrapper around println – Ryan McCullagh Jun 28 '17 at 16:20
  • 1
    @RyanMcCullagh Can you post a more realistic scenario, maybe we can be more helpful? – flavian Jun 28 '17 at 16:29
  • @flavian I've edited my question, please have a look. – Ryan McCullagh Jun 28 '17 at 16:47
  • @flavian: "Converting to a string is a really bad idea." – Yeah, the fact that `Predef` has `any2stringadd` is bad enough. – Jörg W Mittag Jun 28 '17 at 20:06