Home > Blockchain >  Creating an object extending an abstract class and adding it to a sequence of the type abstract clas
Creating an object extending an abstract class and adding it to a sequence of the type abstract clas

Time:12-11

So I have an abstract class and a bunch of objects that extend it:

abstract class Command(val str: String, val help: String):
   def apply(args: Seq[String]): String

object Command:
   var all: Seq[Command] = Seq(Help, Quit, Play, Def)

   def apply(args: Seq[String]): String = 
     //Do some stuff

object Help extends Command("?", "print help"):
   def apply(args: Seq[String]): String = 
     //Do some stuff

object Quit extends Command(":q", "quit this app"):
   def apply(args: Seq[String]): String = 
     //Do some stuff

object Play extends Command("!", "play chord"):
   def apply(args: Seq[String]): String = 
     //Do some stuff

object Def extends Command("def", "define function"):
   def apply(args: Seq[String]): String = 
     case Seq(_, "!", _*) => 
      val name = args.head
      val func = args.tail  
      
      Command.all :  Command(s"$name", func) 

      s"defined $name: $func"
    case _ => ""


As you can see the different objects extends the abstract class, the object Def is a text command where you first enter def to define and then the string seq in apply will be the command itself. As you can see in Def I try to add this new command to the Sequence of commands in the Command-obj. But it doesn't work, and I can't create a val cmd = new Command(s"$name", s"Execute $name") and then work from there. The purpose is to let the user define their own command and since the other commands are created as objects extending the abstract I don't really know how to get there. Any tips?

CodePudding user response:

Not sure if it is what you are referring to, but this does nothing because the result is thrown away.

Command.all :  Command(s"$name", func)

You probably mean

Command.all = Command.all :  Command(s"$name", func)

CodePudding user response:

Came up with a solution: Create a new class which will be called when they enter name from the Def class. If they wanna define a function that plays a E minor chord on a piano they write: def Em ! p 64 67 71 so I Def now name = Em and func = Seq("!", "p", "64", "71") then we create a new instance of Defined and in Defined val command = Seq("p", "64", "67", "71") then we add this instance (of the type Command (the abstract class) to the sequence of Command objects var all: Seq[Command] = Seq(Help, Quit, Play, Def, Em) Now when they enter the command "Em" it will call the apply-function of Play with func = Seq("!", "p", "64", "71") in Play's own apply function. A noticeable flaw here is the Defined's apply doesn't need args: Seq[String] but since every other Object of the type Command needs a sequence in order to give data when calling commands I couldn't see how to avoid it.

class Defined extends Command(s"${Def.name}", s"Execute the function ${Def.name}"){
      //New function every new instance
      val command = Def.func.tail
        def apply(args: Seq[String]): String =
          Play(command) 
}

New class that is based on what they enter in the Def command:

object Def extends Command("def", "Define function"):
  //Accessible by Defined
  var name = ""
  var func = Seq("")
  def apply(args: Seq[String]): String = args match
    case Seq(_, "!", _*) => 
      name = args.head //Ex. Em
      func = args.tail //Ex. ! p 64 67 71

      Command.all = Command.all :  new Defined

      s"defined $name: ${func.mkString(" ")}"
    case _ => ""
  • Related