how can I call a method in auxiliary constructor?
class foo(val x:Int){
def convertToInt(z:string) = {do somthing to convert a string to an integer}
def this(y:string) = this(convertToInt(y))
}
calling convertToInt in auxiliary constructor (this(y:string)) causes this error:
error: not found: value convertToInt
I know I can use a singleton object and pack all static functions like convertToInt into it, but is it a good solution?
object foo{
de开发者_StackOverflow社区f convertToInt(z:string) = {do somthing to convert a string to an integer}
}
class foo(val x:Int){
def this(y:string) = this(foo.convertToInt(y))
}
I think in this case the best solution would be to use factory methods instead of public constructor.
So you can define your constructor private
and provide factory apply
methods in companion object:
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)
You can find more information about constructor vs factory method here:
Constructors vs Factory Methods
It's the same for Scala.
Update
As an example of alternative solution I made very generic solution. Foo
class can now work with any class that ever existed or can be created in future, assuming, that this type can be converted (you can define how it should be converted) to/from 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)
(I could define toOriginal
by just returning = original
, but it would be too boring :)
As you can see, this solution is generic and more complicated. But as far as I saw, many application need some kind of conversion between different primitive values and/or classes. So in many cases it's sutable (and may be event considered very good) solution for many cases and may be for your also. But it's often impossible to tell what's "the best" solution for all possible cases.
by using angle's offer about factory method instead of Auxiliary Constructor:
class Foo(val s:String) {
val s = ""
def bar2:String = s+s
def bar3:List[Char] = s.toList
}
object Foo extends{
def bar1(y:List[Char]):String =y.mkString
def apply(s:String)= new Foo(s)
def apply(y:List[Char])= new Foo(bar1(y))
}
client code:
val foo1 = Foo(List('a','b'))
println(foo1.s)
println(foo1.bar2)
println(foo1.bar3)
Your solution isn't that bad. After all, convertToInt
is similar to a static method in Java. Personally I don't like auxiliary constructors, so I'd normally prefer Easy Angels solution as well. However if you plan to inherit from your class later, the companion object approach won't "scale" for the derived class, you would have to reimplement that method. In that case you should stick with your solution.
Theoretically you could put that method in a separate trait and extend it, but I wouldn't recommend this. Using inheritance should be limited to cases when there is a real dependency, not just for "convenience".
精彩评论