创建一个扩展抽象类的对象并将其添加到 Scala 中类型抽象类的序列中
Posted
技术标签:
【中文标题】创建一个扩展抽象类的对象并将其添加到 Scala 中类型抽象类的序列中【英文标题】:Creating an object extending an abstract class and adding it to a sequence of the type abstract class in Scala 【发布时间】:2022-01-15 05:16:39 【问题描述】:所以我有一个抽象类和一堆扩展它的对象:
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 _ => ""
正如您所见,不同的对象扩展了抽象类,对象 Def 是一个文本命令,您首先输入 def 进行定义,然后 apply 中的字符串 seq 将成为命令本身。正如您在 Def 中看到的,我尝试将此新命令添加到 Command-obj 中的命令序列中。但它不起作用,我无法创建val cmd = new Command(s"$name", s"Execute $name")
然后从那里开始工作。目的是让用户定义自己的命令,因为其他命令是作为扩展抽象的对象创建的,我真的不知道如何到达那里。有什么建议吗?
【问题讨论】:
为每个命令添加新类型感觉几乎没有意义。也许更好的方法是简单地将Command
创建为一个案例类和代表您预定义“命令”的案例类的一堆值。
也许是这样,但这是我得到的,而另一个人想要这样,我还能这样做吗?
我可能会创建一个用户可以输入的带有空 str 参数的类型,但是每次都会覆盖该命令,例如我希望用户输入?并获取命令列表 ?、:q、!、def 以及它们自己定义的命令。
【参考方案1】:
不确定它是否是您所指的,但这无济于事,因为结果被丢弃了。
Command.all :+ Command(s"$name", func)
你可能是说
Command.all = Command.all :+ Command(s"$name", func)
【讨论】:
这确实有帮助,但我的问题正是要添加到 Seq 中,现在解决了。【参考方案2】:想出了一个解决方案:
创建一个新类,当他们从Def
类输入name
时将调用该类。如果他们想定义一个在钢琴上演奏 E 小调和弦的函数,他们会写:def Em ! p 64 67 71
所以我 Def
现在是 name = Em
和 func = Seq("!", "p", "64", "71")
然后我们创建一个 Defined
和 Defined
@ 的新实例987654329@
然后我们将这个实例(Command
(抽象类)类型)添加到命令对象序列var all: Seq[Command] = Seq(Help, Quit, Play, Def, Em)
现在当他们输入命令“Em”时,它将调用Play
的应用函数func = Seq("!", "p", "64", "71")
在 Play 自己的 apply 函数中。这里一个明显的缺陷是 Defined 的 apply 不需要 args: Seq[String]
但由于 Command 类型的所有其他 Object 都需要一个序列才能在调用命令时提供数据,所以我不知道如何避免它.
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)
基于他们在 Def 命令中输入的新类:
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
正如蒂姆指出的那样,如果我不更改 Command
中的 var all
会更好,所以我将其修改为:
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
创建了一个用于保存命令序列的类。所以现在在Def
我访问val cmdSet: commandSet
并使用add
函数然后在object Command
而不是命令序列是一个var 现在def all: Seq[String] = cmdSet.get
返回类CommandSet
中的私有序列
【讨论】:
让类修改其他类中的var
s 确实不是一个好的设计。与其在Command
中使用var
,不如使用包含活动命令列表的单独CommandSet
类。然后Def
可以创建一个新的Command
,并且可以将其添加到CommandSet
以创建一个新的CommandSet
,避免所有使用var
。
感谢您的提示!更新了我的答案。更好?以上是关于创建一个扩展抽象类的对象并将其添加到 Scala 中类型抽象类的序列中的主要内容,如果未能解决你的问题,请参考以下文章