9

My Scala class requires a URL. I could use a String class, but I'd like Java's built in URL validation. What's the best way to allow it to take either a Java Url class, or a String, and, if a String, turn it into a Java Url?

2 Answers 2

8

You can create an implicit conversion from String to URL and accept only URL (this is what you want anyway). The implicit def might be in the companion class or in a helper class/trait (trait in the cake pattern). Something like this:

implicit def `string to url`(s: String) = new URL(s)

Usage:

import the.helper.Container._
//or implement the Helper trait containing the implicit def
val url: URL = "http://google.com"

The drawback is, exceptions might arrive from unexpected places (any might require a further import).

A less implicit approach would be "adding" a toURL method to String, like this:

object Helpers {
  implicit class String2URL(s: String) {
    def toURL = new URL(s)
  }
}

Usage of this would look like this:

import Helpers._
val aUrl = "http://google.com".toURL

Comparison to @m-z's answer: you can combine multiple parameters this way without explosion of combination of different parameters, while for that answer it will exponential (though for small exponents, like in this case 1, that is perfectly fine). @m-z's answer is not reusable, if you need another class, you have to create it again. It works on the library side, so the lib users get a nice documentation, guide how to use it, mine would just work with "magic" and/or small user help (like import of the method, toURL conversion method call). I would choose @m-z's solution for small combinations too, especially with the adjustment of Option or Try. But if you need to overload multiple parameters, I think my solution works better. It really depends on your use case. (You can wrap mine with Try too if there might be cases where the passed url is not valid.)

Sign up to request clarification or add additional context in comments.

Comments

5

You could use an overloaded constructor or apply method:

class A(id: Int, url: URL) {
    def this(id: Int, url: String) = this(id, new URL(url))
}

Or

case class A(id: Int, url: URL)

object A {
    def apply(id: Int, url: String): A = new A(id, new URL(url))
}

1 Comment

IMHO it's better to have an Option[A] or Try[A] for the apply method because new URL may fail.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.