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 _ => ""