如何在辅助构造函数中调用方法?

时间:2011-02-16 08:39:48

标签: scala

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))
}

在辅助构造函数中调用convertToInt(this(y:string))会导致此错误:

error: not found: value convertToInt

我知道我可以使用单例对象并将所有静态函数(如convertToInt)打包到其中,但这是一个很好的解决方案吗?

object foo{
    def 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))
}

3 个答案:

答案 0 :(得分:14)

我认为在这种情况下,最好的解决方案是使用工厂方法而不是公共构造函数。

因此,您可以在随播对象中定义构造函数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)

您可以在此处找到有关构造函数与工厂方法的更多信息:

Constructors vs Factory Methods

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,但这太无聊了:)

如您所见,此解决方案通用且更复杂。但据我所知,许多应用程序需要在不同的原始值和/或类之间进行某种转换。因此,在许多情况下,它对于许多情况而言是可靠的(并且可能被认为是非常好的事件)解决方案,并且可能对您而言也是如此。但是,对于所有可能的情况,通常无法确定什么是“最佳”解决方案。

答案 1 :(得分:2)

使用角度提供的工厂方法而不是辅助构造函数:

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))
}

客户代码:

val foo1 = Foo(List('a','b'))
println(foo1.s)
println(foo1.bar2)
println(foo1.bar3)

答案 2 :(得分:0)

你的解决方案并不是那么糟糕。毕竟,convertToInt 类似于Java中的静态方法。我个人不喜欢辅助构造函数,所以我通常也喜欢Easy Angels解决方案。但是,如果您计划稍后从您的类继承,则伴随对象方法将不会为派生类“缩放”,您将不得不重新实现该方法。在这种情况下,你应该坚持你的解决方案。

理论上你可以将该方法放在一个单独的特征中并扩展它,但我不建议这样做。使用继承应限于存在真实依赖关系的情况,而不仅仅是“方便”。