Подтвердить что ты не робот

Реализация одного конструктора Scala, который делает больше, чем заданные переменные

В большинстве случаев конструктор для класса не более чем принимает значения аргумента и использует их для установки переменных экземпляра:

// Java
public class MyClass {
   private int id;

   public MyClass(int id) {
      this.id = id;
   }
}

Итак, я понимаю эффективность синтаксиса конструктора Scala по умолчанию... просто объявляя список переменных в круглых скобках рядом с именем класса:

// Scala
class MyClass(id: int) {
}

Однако, как насчет тех обстоятельств, когда вам нужен конструктор, чтобы на самом деле делать STUFF, кроме простого подключения аргументов к переменным экземпляра?

// Java
public class MyClass {
   private String JDBC_URL = null;
   private String JDBC_USER = null;
   private String JDBC_PASSWORD = null;

   public MyClass(String propertiesFilename) {
      // Open a properties file, parse it, and use it to set instance variables.
      // Log an error if the properties file is missing or can't be parsed.
      // ...
   }
}

Как это работает в Scala? Я могу попытаться определить реализацию для этого конструктора следующим образом:

// Scala
class MyClass(propertiesFilename: String) {
  def this(propertiesFilename: String) {
    // parse the file, etc
  }
}

... но я получаю ошибку компиляции, жалуясь, что конструктор определяется дважды.

Я мог бы избежать этого конфликта, создав конструктор по умолчанию no-arg, а затем объявив выше как перегруженный вторичный конструктор. Однако, как насчет ситуаций, в которых вам действительно нужен конструктор "один-единственный-один", и вам нужно это делать?

4b9b3361

Ответ 1

Вы можете выполнять эти действия просто в теле класса.

Class Foo(filename: String) {
    val index =  {
         val stream = openFile(filename)
         readLines(stream)
         ...
         someValue
     }
     println("initialized...") 
}

Ответ 2

Любой код, который вы помещаете в тело класса, выполняется при построении

class MyClass(propertiesFileName: String) {
  println("Just created an instance of MyClass with properties in " + propertiesFileName)
  val myFavoriteProperty = retrieveFavoriteFrom(propertiesFileName)
}

Это может быть немного неудобно, и, конечно же, не очень хорошо чередоваться с объявлением участника и кодом инициализации, но это небольшая цена, чтобы заплатить за удобство синтаксиса инициализации переменной