Reputation: 41
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?
Upvotes: 0
Views: 378
Reputation: 41
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"):
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.cmdSet.add(new Defined)
s"defined $name: ${func.mkString(" ")}"
case _ => ""
def getName: String = name
def getFunc: Seq[String] = func
As Tim pointed out it's better if I don't change the var all
in Command
so I modified it to this:
class CommandSet:
private var commandSet: Seq[Command] = Seq(Help, Quit, Play, Def)
def add(command: Command): Unit =
commandSet = commandSet :+ command
def get: Seq[Command] =
commandSet
object Command:
val cmdSet = new CommandSet
def all: Seq[Command] = cmdSet.get
Created a class which purpose is to hold a sequences of Commands. So now in Def
I access val cmdSet: commandSet
and use the add
function and then in object Command
instead of the sequences of commands being a var it's now def all: Seq[String] = cmdSet.get
returning the private sequence in the class CommandSet
Upvotes: 0
Reputation: 27356
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)
Upvotes: 1