当前位置: 首页 > 知识库问答 >
问题:

如何为类创建工厂?

万俟皓
2023-03-14

我有以下代码:

class kg is Dimension {
    method new() {
        return self.bless(
                :type('mass'),
                :abbr('kg'),
                :multiplier(Multiplier.new(
                        numerator =>   1.0,
                        denominator => Quantity.new(1000.0, 'g')))),
    }
}

class mg is Dimension {
    method new() {
        return self.bless(
                :type('mass'),
                :abbr('mg'),
                :multiplier(Multiplier.new(
                        numerator =>   1000.0,
                        denominator => Quantity.new(1.0, 'g')))),
    }
}

我将添加更多类似的类。与其单独拼出所有这些类,我想学习如何创建一个可以从简单的数据结构创建这些类的工厂。

我该怎么做?我阅读了Metaobject协议文档,但根据文档页面顶部和中间的示例,我不知道如何动态地为我的类指定不同的名称。

我试过:

constant A := Metamodel::ClassHOW.new_type( name => 'A' );
A.^add_method('x', my method x(A:) { say 42 });
A.^add_method('set', my method set(A: Mu \a) { A.^set_name(a) });
A.^compose;

my $bar = A;
$bar.set('Foo');
say $bar.^name;  # 
A.x;             # works
Foo.x;           # error

但最后一行只是抛出了一个错误:

Undeclared name:
    Foo used at line 13

共有1个答案

仰城
2023-03-14

您应该意识到的第一件事是,任何类型的元编程通常都需要在编译时完成,也就是在BEGIN块中。

其次:目前,Raku具有一些用于创建代码的元编程功能,但并非所有功能都需要使其尽可能轻松。RakuAST的工作将改变这一点,因为它基本上使Raku本身是从公共元编程API构建的(而不是你可以争辩的是,当前的引导版本使用了大量NQP)。

我已将您的代码重写为以下内容:

sub frobnicate(Str:D $name) {
    my \A := Metamodel::ClassHOW.new_type(:$name);
    A.^add_method('x', my method x() { say 42 });
    A.^compose;
    OUR::{$name} := A;
}

BEGIN frobnicate("Foo");
say Foo.^name;  # Foo
Foo.x;          # 42

因此,这引入了一个名为frobnite的子类,它创建了一个具有给定名称的新类型。向其中添加方法x,并组成新类型。然后确保它在当前编译单元中被称为我们的。

然后,在编译时通过在BEGIN前面加前缀来调用frobnite子脚本。这一点很重要,因为在编译下一行时,将无法知道其他的Foo,因此可能会出现错误。

目前有一个小问题:

dd Foo.^find_method("x").signature;  # :(Mu: *%_)

未设置发票约束。我还没有找到一种方法(在RakuAST之前)使用元编程接口来设置它。但我认为这不会成为你举的例子的问题。如果这确实成为一个问题,那么当我们到达那里时,让我们穿过那座桥。

 类似资料:
  • 问题内容: 我想创建我现有的swift类的类别,但是IDE中没有选择这样做的选项。 知道在快速项目中是否存在类别?还是如何在Swift项目中实现类似的功能? 问题答案: 在Swift中,您可以用来向现有的类,结构和枚举类型添加新功能。 它们在一些方面与Objective-C类别有所不同,主要是: 他们没有名字 您不需要显式导入扩展。如果定义扩展以将新功能添加到现有类型,则新功能将在该类型的所有现有

  • 问题内容: mvnrepository中的artifcats上有徽标。找不到解决办法。示例:http://mvnrepository.com/artifact/org.apache.nifi/nifi- api 这是我的工件,图标为{h}:https : //mvnrepository.com/artifact/ru.sadv1r.vk/vk- parser 怎么改变呢? 问题答案: 您应该能够在

  • 从继续https://stackoverflow.com/a/51132333/936293,为什么以下操作不起作用? 最后一行导致编译器错误: “{email:string;}”类型的参数不可分配给“MemberModel”类型的参数。键入“{email:string;}”不可分配给类型“Document”。类型“{email:string;}”中缺少属性“increment”。 < code

  • 通过大量的试验和错误,我已经在我的沙盒中创建了功能触发器。我的问题是,我现在想把它应用到我的实时组织中,但我似乎无法理解整个顶点类的事情。 如何创建类? 我的触发器背后的想法是,当保存opportunity记录时,soql查询将查看在“类别”字段中选择的选取列表值,并找到具有匹配名称的活动供应商或成员服务帐户类型,并带出其salesforce id。将该sfid拖到“我的供应商名称查找”字段中,将

  • 问题内容: 我想为工具提示创建一个自定义CSS类,该类将包裹长度超过25-30的字符串。通常这样长的文本不适合tootltip文本区域。 而且是否有使用[工具提示ui.bootstrap.tooltip)进行此操作?就像使用自定义CSS类来获取所需的输出。 这是简单的CSS工具提示 这是相同的代码片段: 问题答案: CSS解决方案 对于眼前的问题有一个非常简单的解决方案。我基本上添加的是以下CSS

  • 我正在使用ApacheCommonsHttpClient 4.3。x和spring3。我正在尝试将connectionpool与其关联的socketconfig实例连接起来。 http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConn