Как я могу вызвать метод во вспомогательном конструкторе? - PullRequest
8 голосов
/ 16 февраля 2011
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 ]

14 голосов
/ 16 февраля 2011

Я думаю, что в этом случае лучшим решением будет использование фабричных методов вместо открытого конструктора.

Таким образом, вы можете определить свой конструктор 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, но это было бы слишком скучно:)

Как видите, это решение является общим и более сложным. Но, как я видел, многие приложения нуждаются в некотором преобразовании между различными примитивными значениями и / или классами. Так что во многих случаях это подходящее (и может считаться событием очень хорошим) решение для многих случаев и может быть для вас тоже. Но зачастую невозможно сказать, какое «лучшее» решение для всех возможных случаев.

2 голосов
/ 17 февраля 2011

, используя предложение угла о заводском методе вместо вспомогательного конструктора:

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)
0 голосов
/ 16 февраля 2011

Ваше решение не так уж и плохо. В конце концов, convertToInt похож на статический метод в Java. Лично мне не нравятся вспомогательные конструкторы, поэтому я бы тоже предпочел решение Easy Angels. Однако если вы планируете наследовать от своего класса позже, подход сопутствующего объекта не «масштабируется» для производного класса, вам придется переопределить этот метод. В этом случае вы должны придерживаться своего решения.

Теоретически вы можете поместить этот метод в отдельную черту и расширить его, но я бы не рекомендовал это. Использование наследования должно быть ограничено случаями, когда существует зависимость real , а не только для «удобства».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...