Dynami c полиморфизм в Scala - PullRequest
       2

Dynami c полиморфизм в Scala

0 голосов
/ 27 марта 2020

Мне нужно изменить поведение объекта во время выполнения.
У меня есть два конкретных (одноэлементных) класса объектов Dog и Cat, оба выходят из абстрактного класса Animal.
Объект animal типа Animal должен быть изменен на Dog или Cat во время выполнения.
Вот примерный код чего-то, что я пытаюсь выполнить sh:

abstract class Animal() {
    def sound: Unit
}

object Cat extends Animal {
    def sound: Unit = {
        print("meow")
    }
}

object Dog extends Animal {
    def sound: Unit = {
        print("bark")
    }
}

object MyProgram {
    val animal: Animal = _

    def initialize(config: Config): Unit ={
        // check the config
        if (config.getString("ANIMAL_TYPE").equals("Dog")) {
            animal = Dog
        } else {
            animal = Cat
        }

    }

    def run: Unit = {
        animal.sound
    }
}

def main(): Unit = {
    val config = ConfigFactory.praseFile(myconfigfile)
    MyProgram.initialize(config)
    MyProgram.run
}

Можно ли сделать что-то подобное в Scala? Если нет, то как я могу выполнить это sh в Scala.

Ответы [ 3 ]

1 голос
/ 27 марта 2020

Ошибка, которую вы получаете, не имеет ничего общего с набором или динамическим c полиморфизмом:

           var animal : Animal = _
               ^
On line 19: error: local variables must be initialized

Как вы видите, в типах в вашей программе нет ничего плохого, вам просто нужно правильно инициализируйте вашу переменную:

def main() : Unit = {
    var animal = if(config.getString("ANIMAL_TYPE").equals("Dog")) {
        Dog
    } else {
        Cat
    }

    // this should print either bark or meow 
    animal.sound
}

Обратите внимание, что в вашем коде есть пара не-идиоматических вещей c. Более идиоматическая версия c будет выглядеть примерно так:

trait Animal {
    val sound: String
}

object Cat extends Animal {
    override val sound = "meow"
}

object Dog extends Animal {
    override val sound = "bark"
}

def main(): Unit = {
    val animal = if (config.getString("ANIMAL_TYPE").equals("Dog")) Dog else Cat

    // this should print either bark or meow 
    print(animal.sound)
}
  • Используйте trait вместо abstract class.
  • Не используйте пустой конструктор / initializer, просто не используйте конструктор / инициализатор.
  • Отдельный ввод / вывод от вычислений: печать должна выполняться методом main, а не Animal.
  • . явный модификатор override.
  • Не используйте аннотации типов, если тип очевиден.
  • Не используйте фигурные скобки вокруг одиночных выражений.
  • Не используйте var, всегда используйте val.
  • if - это выражение, не игнорируйте его возвращаемое значение.
0 голосов
/ 27 марта 2020

Ваш код должен работать почти так, как есть, просто назначьте что-нибудь животному.

object MyProgram {
    //First of all use some default value for animal. 
    //It will be safer to use. 
    var animal: Animal = Cat 
    // or use explicitly null if there is no sensible default value. 
    // underscore makes it less clear what will happen.
    //var animal: Animal = null 

    //I thing match is better than if/else here especially when third animal will arrive. You can assign it like that:
    def initialize(config: Config): Unit ={
        animal = (config.getString("ANIMAL_TYPE") match {
            case "Dog" => Dog
            case _ => Cat 
        } 
    }
}
0 голосов
/ 27 марта 2020

Вы неправильно определяете функцию main.

Функция main должна быть членом некоторого object и иметь аргумент типа Array[String].

object SomeRandomName {
  def main(): Unit = {
    var animal: Animal = null

    // check the config
    if(config.getString("ANIMAL_TYPE").equals("Dog")) {
        animal = Dog
    } else {
        animal = Cat
    }

    // this should print either bark or meow 
    animal.sound
  }
}

И этот код должен скомпилироваться и хорошо работать.

SIDENOTE : Если вы используете Scala 3 (вместо Scala 2 .x), тогда вам не нужно создавать объект-оболочку для функции main. Функция может быть на верхнем уровне.

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