Я думаю, что в этом случае лучшим решением будет использование фабричных методов вместо открытого конструктора.
Таким образом, вы можете определить свой конструктор private
и предоставить фабрике apply
методы в сопутствующем объекте:
class Foo private (val x:Int)
object Foo {
def apply(i: Int) = new Foo(i)
def apply(s: String) = new Foo(convertToInt(s))
def convertToInt(s: String) = s.toInt
}
println(Foo(512).x)
println(Foo("256").x)
Более подробную информацию о конструкторе или фабричном методе * можно найти здесь:
Конструкторы против фабричных методов
То же самое для Scala.
Обновление
В качестве примера альтернативного решения я сделал очень общее решение. Foo
класс теперь может работать с любым классом, который когда-либо существовал или может быть создан в будущем, при условии, что этот тип может быть преобразован (вы можете определить, как он должен быть преобразован) в Int
:
trait Convertable[From, To] {
def convert(from: From): To
}
object Convertable {
implicit val intString = new Convertable[Int, String] {
def convert(from: Int) = from toString // your logic here
}
implicit val stringInt = new Convertable[String, Int] {
def convert(from: String) = from toInt // your logic here
}
implicit def self[T] = new Convertable[T, T] {
def convert(from: T) = from
}
}
case class Foo[T](original: T)(implicit toInt: Convertable[T, Int], fromInt: Convertable[Int, T]) {
val x: Int = toInt convert original
def toOriginal = fromInt convert x
}
println(Foo(512) x)
println(Foo("256") x)
(я мог бы определить toOriginal
, просто вернув = original
, но это было бы слишком скучно:)
Как видите, это решение является общим и более сложным. Но, как я видел, многие приложения нуждаются в некотором преобразовании между различными примитивными значениями и / или классами. Так что во многих случаях это подходящее (и может считаться событием очень хорошим) решение для многих случаев и может быть для вас тоже. Но зачастую невозможно сказать, какое «лучшее» решение для всех возможных случаев.