To get more type safety in our code base we have started to replace generic Strings, Ints etc. with type safe value classes, but I am struggling to get them working conveniently with the == operator and literals. Hopefully someone can help me out.
Our value classes are defined and used like this:
case class Name(value: String) extends AnyVal {} object Name { implicit def to(something:String): Name = Name(something) // convenience } case class Address(value: String) extends AnyVal {} object Address { implicit def to(something:String): Address = Address(something) // convenience } case class Person(name: Name, address: Address) { def move(newAddress: Address) = copy(address=newAddress) } val somebody = Person("Pete", "Street 1") somebody.move(Address("Street 2")) // allowed somebody.move(somebody.name) // not allowed, which is exactly what we want somebody.move("Street 2") // allowed by convenience Now, I would like them to compare "naturally" on their inner value:
Name("Pete") == "Pete" // should be true, but evaluates to False I can sort of fix this by overriding equals like this:
case class Name(value: String) extends AnyVal { override def equals(other: Any) = if (other.isInstanceOf[Name]) other.asInstanceOf[Name].value == this.value else if (other.isInstanceOf[String]) other == this.value else false } Name("Pete") == "Pete" // now evaluates to true However, this solution is not symmetric:
"Pete" == Name("Pete") // evaluates to false, because it is using String.equals I do not know how to fix this. Not even declaring an implicit conversion from Name to String helps (and I would much prefer not to have such a thing). Is it possible to do what I am trying to do?
EDIT: I probably failed to be clear on this, but I am not really looking for advice on software development. This is meant to be a technical question: Can it be done in Scala or not?
I have some reasons for doing what I have described, but sadly they relate to a codebase of tens of thousands of lines of Scala code, and cannot be conveyed in a short stack overflow question.
"Pete"andName("Pete")are different entities?