我目前正在Twitch频道的聊天机器人上工作,并且希望将所有命令作为程序中的单独类,以便只需要添加或删除单个类即可添加或删除命令。
我已经在互联网上搜索了很长时间,但从未遇到合适的设计。以下是我认为的外观,但找不到正确的语法。
class Command()
{
string keyword;
int globalCooldown;
List<string> args;
}
class DoStuffA : Command(List<string> _args)
{
keyword = "pleasedostuffa";
globalCooldown = 2;
args = _args;
DoStuff(List<string> args)
{
//doing stuff A here with all the logic and so on
}
}
class DoStuffB : Command(List<string> _args)
{
keyword = "pleasedostuffb";
globalCooldown = 8;
args = _args;
DoStuff(List<string> args)
{
//doing stuff B here with all the logic and so on
}
}
我之所以需要它,是因为我想将所有可能的命令存储在List<Commands>
中,并且当出现新的聊天消息时,使用chat命令搜索该列表中的哪个对象与keyword
匹配,然后执行适当的功能。例如,如果有人发布!pleasedostuffa
,我将执行
foreach (Command c in commands)//commands is List<Command>
{
if(c.keyword==receivedCommand.command)//.command is string
{
c.DoStuff(receivedCommand.argsAsList)//.argsAsList is List<string>
}
}
我希望我能正确地解释这一点,并且真的很希望至少对如何实现这一点有所了解。
提前谢谢!
答案 0 :(得分:0)
您几乎可以正确设置方法,尽管还需要进行其他一些更改。您需要让基类将DoStuff()公开为虚拟方法。试试这个:
public abstract class Command
{
public string keyword;
public int globalCooldown;
//List<string> args;
public abstract void DoStuff(List<string> args);
}
public class DoStuffA : Command
{
//public string keyword = "pleasedostuffa";
//public int globalCooldown = 2;
//args = _args;
public DoStuffA()
{
keyword = "pleasedostuffa";
globalCooldown = 2;
}
public override void DoStuff(List<string> args)
{
//doing stuff A here with all the logic and so on
}
}
public class DoStuffB : Command
{
//public string keyword = "pleasedostuffb";
//public int globalCooldown = 8;
// args = _args;
public DoStuffB()
{
keyword = "pleasedostuffb";
globalCooldown = 8;
}
public override void DoStuff(List<string> args)
{
//doing stuff B here with all the logic and so on
}
}
因此,有几点注意事项。
方法继承
在这里,我将基类设为抽象,只是为了强制每个子命令都实现抽象功能DoStuff()
。毕竟,您将如何处理基类的实例?它不会做任何事情,因为您没有实际的实现。因此,抽象既可以避免意外实例化Command本身,又可以确保子类型实现者做正确的事情。
第二,在子类级别,您需要override
在基类上的方法。这样可以确保调用((Command)doStuffB).DoStuff()
的任何对象都能正确实现该函数。
现在,您在Command上具有DoStuff()方法,您的foreach
循环应可以正常工作。您可以在基类上使用该方法,因此可以在不强制转换的情况下运行子级的虚拟替代。
基类成员访问权限
您要在此处声明的字段keyword
和globalCooldown
并不是人们通常会公开这样的信息的方式,但是在我们开始之前,我将先解释更多从继承的类访问基类成员的基本原理。
这两个字段需要标记为public
(并指定适当的类型),以便可以在类外部(在您的foreach中)使用它们。 public
关键字称为可访问性修饰符,还有其他一些可访问性选项,但就您而言,只有public
可能会做您想要的事情。
如您所见,我已经注释掉了子类中的字段。如果在此处声明它们,它们将隐藏(但不会覆盖)基类上具有相同名称的成员。字段没有等效的virtual
或abstract
,因此您需要另一种策略。在这里,我们将这些字段的原始声明保留在基类上,以便拥有任何命令类型的任何人都可以使用它们。但是,我们无需在子类级别上重新声明它们,而只是在子类的构造函数中设置基类成员的值。
请注意,为清楚起见,您可以使用base.keyword = "etc";
来明确指定要在基类上设置成员。
通过属性公开内部值
正如我指出的那样,这是可行的,但这并不是大多数人公开keyword
和globalCooldown
值的方式。为此,通常应使用属性。这使您可以存储和公开值,而不必冒险让某人(有意或无意)更改值。在这种情况下,您需要这样声明属性:
public string Keyword // properties start with a capital letter by convention
{
get; // The get accessor is public, same as the overall property
protected set; // the set accessor is protected
}
protected
集访问器意味着仍可以由子类(而不是其他任何人)来设置。这可能就是您想要的。因此,现在,在子构造函数中,您可以设置base.Keyword = "whatever";
,并且foreach
代码可以引用但不能覆盖该值。您可以通过类似的方式声明GlobalCooldown。