(imagine that I can identify an user either by name or numeric id)
You almost certainly don't want to do this by having optional fields in your class. Rather, you should encode the fact that the user is identified in various ways into the types and structure of your program.
One way to do this is to encode the user identifier using Scala's built-in Either type:
class User private(identifier : Either[String, Int]) {
def this(id : Int) = this(Right(id))
def this(name : String) = this(Left(name))
}
However, you might also want to make the nature of the user identifier a little more explicit, and encode it as your own Algebraic data type:
trait UserIdentifier
object UserIdentifier {
case class ById(id : Int) extends UserIdentifier
case class ByName(name : String) extends UserIdentifier
}
class User(id : UserIdentifier) {
def this(id : Int) = this(UserIdentifier.ById(id))
def this(name : String) = this(UserIdentifier.ByName(name))
}
By doing it this way, you prevent problems such as somebody trying to look up a name on a User which is identified by an id instead. The second approach also allows you to extend the idea of a UserIdentifier in the future, in case a user can be identified by some other construct.