[Scala] Konstruktory z argumentami różnego typu

[Scala] Konstruktory z argumentami różnego typu
Julian_
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1703
0

Mam klasę:

Kopiuj
class Config (props: Properties) {

}

i chcę mieć możliwość inicjowania jej na 3 sposoby:

Kopiuj
  new Config();
  new Config(new Properties());
  new Config("file://.config/myapp/config.xml");

Jak zmodyfikować klasę Config by było to możliwe?

Doszedłem jedynie do tego:

Kopiuj
class Config private(props: Properties) {

}

object Config {

  def apply(): Config = {
    apply(new Properties())
  }

  def apply(path: String): Config = {
    val props: Properties = new Properties()
    props.load(new FileInputStream(path))
    apply(props)
  }

  def apply(props: Properties): Config = {
    return new Config(props)
  }
}

ale wtedy nie mogę użyć new przy tworzeniu Config.

Wibowit
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: XML Hills
1

Da się to zrobić (secondary constructors), ale po co? Metody fabrykujące apply w companion object to rozwiązanie idiomatyczne.

stivens
  • Rejestracja: dni
  • Ostatnio: dni
0

Skoro roznego typu to to nie powinna byc jakas fabryka?

Kopiuj
Foo.fromBar(bar)
Foo.fromBuzz(buzz)

Nie wiem czy to idiomatyczne ale taka pierwsza mysl.

Edit: a po co Ci to new?

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5549
0
Kopiuj
class Config private(props: Properties) {
  def this() = this(new Properties())
  def this(path: String) = {
    val props: Properties = new Properties()
    props.load(new FileInputStream(path))
    this(props)
  }
}

Ale to co Ty napisałeś jest uważane za lepsze przez community Scali niż to co ja napisałem

KamilAdam
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Silesia/Marki
  • Postów: 5549
1

działa Ci to? Bo this() musi być chyba pierwszy.

Oczywiście że nie. Pisałem to na na pół śpiąco :P
(BTW dlatego wersja z metodami statycznymi jest lepsza)
Ale można to łatwo przerobić na :

Kopiuj
class Config private(props: Properties) {
  def this() = this(new Properties())
  def this(path: String) = this(Config.load(path))
}

object Config {
  private def load(path: String) : Properties = {
    val props = new Properties()
    props.load(new FileInputStream(path))
    props
  }
}
Julian_
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1703
0

To moje rozwiązanie uniemożliwia dziedziczenie tych konstruktorów:

Kopiuj
class Config (props: Properties) {

}

class ConfigChild (path: String) extends Config(path) // !!!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.