0

So I am trying to create a game and the user can has to choose 1 hero from a pool of heroes. How should I create the object of the user's chosen hero? Basically I am trying to create an object according to the user input

Edit: I realize that just putting one paragraph is not enough and that I should add my code structure as well. Currently I have a hero class and every other hero extends from this class, so I am trying to do something like this

class Hero {
}

class Bob extends Hero{ //Bob is one of the heroes that the user can choose
    def skill1() { //the skills that Bob can use
    }
}

class Player() {
    val hero //player's hero option will be stored here
}

class Game { //gamedata will be stored here
    val player: Player = new Player()
}

class Controller {
    def selectHero {  //this is where the user inputs a number from 1 to 10 and the app will create a hero object

    }
}

I am stuck at the selectHero method and do not know how to proceed. I tried doing something like this:

 val _hero1: Hero = (
     if (option1 == 1) {
         new Bob()
     }  
     else if (option1 == 2) {
         new James()
     }  
     else if (option1 == 3) {
         new Jimmy()   
     }
     else { 
         null
     }
 )

But I ended up not being able to access their skills since parent classes cannot access the methods of child classes, can anyone help?

Chris
  • 26,361
  • 5
  • 21
  • 42

1 Answers1

0

Here is an idea: You can read from stdin a number and create as many heroes as you want until you want to break the loop. Using inheritance and polymorphism, your call to skills() will dynamically bound to the class of that hero object.

There are a lot of improvements you can do from here:

  • You still have to use a try-catch block to avoid a NumberFormatException, when inputing something that is not an Int.
  • You need to define toString() on every class that extends Hero. Currently when printing heroes, we get the objects, not their string representations.
  • You would be better with a Hero factory method than with a pattern match.
  • Consider making the Hero classes into objects if they are unique, or consider making them case classes if you need to pattern match on them.
    import scala.collection.mutable
    import scala.io.StdIn.readLine
    import scala.util.control.Breaks.{break, breakable}
    
    object Test extends App {
    
      abstract class Hero {
        def skills(): Unit
      }
    
      class Bob extends Hero {
        def skills(): Unit =
          println("This is Bob. His skills are partying like a Hero")
      }
    
      class James extends Hero {
        def skills(): Unit =
          println("This is James. His skills are drinking like a Hero")
      }
       
      class Jimmy extends Hero {
        def skills(): Unit =
          println("This is Jimmy. His skills are gaming like a Hero")
      }
    
      object Controller {
        def selectHero(option: Int): Hero = option match {
          case 1 => new Bob()
          case 2 => new James()
          case 3 => new Jimmy()
          case _ => break
        }
      }
    
      val heroes = mutable.Set.empty[Hero]
    
      breakable {
        while (true) {
          val hero = Controller.selectHero(readLine().toInt)
          hero.skills()
          heroes += hero
        }
      }
    
      println(heroes)
      // process heroes further
    
      println("done")
    }

Output based on input:

    1
    This is Bob. His skills are partying like a Hero
    2
    This is James. His skills are drinking like a Hero
    3
    This is Jimmy. His skills are gaming like a Hero
    4
    HashSet(Test$James@337d0578, Test$Jimmy@61a485d2, Test$Bob@69d9c55)
    done
Alin Gabriel Arhip
  • 2,568
  • 1
  • 14
  • 24
  • 1
    thanks, your code suggestion was pretty helpful. The factory method you mentioned was also pretty helpful, I will probably look into that more since that I think the factory method will suit my code better – FrenchFryKid Jun 23 '22 at 05:06
  • ` case _ => break` it will not work here, because Unit (void) is not a Hero. FrenchFry, do you see to create object (commonly Bob is an object, not a class), or you really wanna have a classes? – Mikhail Ionkin Jun 24 '22 at 20:35
  • You would be correct, except for the fact that `break` has type `Nothing`: `def break(): Nothing = throw breakException` And since Nothing is a subtype of every other type, it works. I do agree that `Bob` should be an `object`, though, and I am aware that using `break` in Scala is not encouraged, but it often goes hand-in-hand with `while(true)` loops. – Alin Gabriel Arhip Jun 24 '22 at 20:48
  • @MikhailIonkin I am not particularly sure to be honest. I did find out that most people use objects for these types of scenarios, but I am not sure why. Can you please explain why Bob should be an object here instead of a class? Also, to answer your question, I do not really want to have classes. I just want it so that the heroes can be created. – FrenchFryKid Jun 25 '22 at 13:32
  • @FrenchFryKid, both class and object are possible variants. If you wanna game where player can choose one of few (limited) heroes (Bob, Alice or Jack), and if each of these characters have significant differences in behavior and/or scenarious, than you probably should prefer classes of Bob, Alice and Jack. Otherwise, when differences if only about name, skin, age and so on, you probably should prefer object. Commonly there is 2nd case, but not always. Also you can google this question, e.g., https://stackoverflow.com/questions/1215881/the-difference-between-classes-objects-and-instances – Mikhail Ionkin Jun 27 '22 at 05:26