实例化一个 Raku 类,并在构造函数中更新一个实例变量

cam*_*art 10 raku

我似乎很难理解如何正确使用 Raku 中的类。

我正在尝试创建一个“数据库”类,我将在整个 cro 应用程序中使用该类。但是我似乎不明白如何在对象构造(构建?)时处理设置实例变量。

下面的类显示了我在调用它时遇到的问题的示例:

调用:

my $db = Database.new(dsn => 'update me!');
say "what value is foo: " ~ $db.what-is-foo(); # prints "what value is foo: 0" but expecting 123
Run Code Online (Sandbox Code Playgroud)

我的课:

use DB::Pg;

class Database {
    has Str    $.dsn is required;
    has DB::Pg $!dbh = Nil;
    has Int    $!foo = 0;

    method new (:$dsn) {
        my $dbh = DB::Pg.new(conninfo => :$dsn);
        my $foo = 123;
        return self.bless(:$dsn, dbh => $dbh, foo => $foo);
    }

    method what-is-foo() {
        return $!foo;
    }
}
Run Code Online (Sandbox Code Playgroud)

所以在我的类构造函数中,我想为数据库 dsn 传入一个命名的 arg。在我计划连接的新方法中,并为连接句柄设置一个实例变量。

在这个例子中,我使用一个简单的整数 (foo) 作为测试。

到目前为止,我发现这里的文档不包含此类模式的示例,除了 pehaps:

use DB::Pg;

class Database {
    has Str    $.dsn is required;
    has DB::Pg $!dbh = Nil;
    has Int    $!foo = 0;

    submethod BUILD(:$dsn) {
        $!dbh = DB::Pg.new(conninfo => :$dsn);
        $!foo = 123;
    }

    method what-is-foo() {
        return $!foo;
    }
}
Run Code Online (Sandbox Code Playgroud)

但这给了我:

The attribute '$!dsn' is required, but you did not provide a value for it.
Run Code Online (Sandbox Code Playgroud)

任何帮助将不胜感激!

use*_*601 10

只有具有公共访问器(即.twigil)的属性才会使用bless.

你有两种方法来处理这个问题。您可以将它们设置为TWEAKBUILD,或者您可以将属性添加到属性中is built以自动为您完成此操作。is built在这种情况下,该属性可能是最简单的,只需说has Int $!foo is built = 0. 但值得扩展其他选项:

如果您包含BUILD方法,则您需要自行负责所有设置。这意味着公共属性私有属性。但是您可以通过巧妙地命名参数来让您的生活更轻松:

method BUILD (:$!dsn, :$!dbh, :$!foo) { }
Run Code Online (Sandbox Code Playgroud)

其实就是这样。签名将传入的值绑定到$!dsn等,这当然会为整个对象实例设置它们。当然,你也可以在这里做更有趣的事情。在任何情况下,在 之后BUILD,都会进行一些额外的检查。(1)如果你没有设置$!dsn,因为你有is required,就会出现错误。(2) 如果您最终没有设置$!fooor $!dbh,它们将收到它们的默认值。

使用TWEAK,您将获得与使用 相同的参数BUILD,但所有初始设置都已完成(构建或自动绑定到公共属性,以及所有默认值,并保证所需值存在)。你只是有机会做一些最后一秒的调整。

  • 这是一个很好的答案并且解释了很多。谢谢你!在这种情况下,我走的是构建路线。但我有了更好的理解,这让我相信在不久的将来我一定会使用 TWEAK (3认同)
  • 相反,如果您希望某个属性具有访问器,但*不*可以在对象创建时设置它,您可以说“has $.foo isbuilt(False)”。遗憾的是,目前还没有允许“has $.foo is !built”的语法糖。 (3认同)
  • 我认为有动力更新文档以使用 TWEAK 而不是 BUILD。这个想法是十分之九是你想要的。另一次你可能想要 BUILD,然后你可能想要编写一个新方法。 (2认同)