I am reading a Spark in Action book, I came across a construct that even after a while working with Scala I still can't understand. Here is the code (complete code) :
First we have a case class where RDD will be converted to DataFrame using this case class:
     import java.sql.Timestamp
        case class Post(
          commentCount:Option[Int],
          lastActivityDate:Option[java.sql.Timestamp],
          ownerUserId:Option[Long],
          body:String,
          score:Option[Int],
     ... ) 
Then we define an object with implicit class
object StringImplicits {
    implicit class StringImprovements(val s: String) {
    import scala.util.control.Exception.catching
    def toIntSafe = catching(classOf[NumberFormatException]) opt s.toInt
    def toLongSafe = catching(classOf[NumberFormatException]) opt s.toLong
    def toTimestampSafe = catching(classOf[IllegalArgumentException]) opt
      Timestamp.valueOf(s)
  }
}
Then we import the object which is already in scope for some reason and now looks like all String object has the three methods defined in StringImprovements
import StringImplicits._
def stringToPost(row: String): Post = {
  val r = row.split("~")
  Post(r(0).toIntSafe,
    r(1).toTimestampSafe,
    r(2).toLongSafe,
    r(3),
    ... 
}
Questions:
- Why do we need to need to import an already in scope object?
- Which statement exactly assigned these methods to the String object, this is so confusing?
Reading implicit classes doc it makes some sense but not everything is clear. For example how come this is a valid expression
scala> 5 times println("HI")
I understand if it was
IntWithTimes(5).time(println("HI")) 
 
     
    