实例化一个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

我的课:

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;
    }
}

所以在我的类构造函数中,我想为数据库 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;
    }
}

但这给了我:

The attribute '$!dsn' is required, but you did not provide a value for it.

任何帮助将不胜感激!

回答

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

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

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

method BUILD (:$!dsn, :$!dbh, :$!foo) { }

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

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

  • That's an excellent answer and explains a lot. Thankyou! In this case I went down the is built route. But I have a better understanding which leads to be believe I will undoubtable use TWEAK at some time in the near future
  • Conversely, if you want an attribute to have an accessor but *not* have it settable at object creation, you can say `has $.foo is built(False)`. Sadly there is **no** syntactic sugar yet for allowing `has $.foo is !built`.
  • I think there is a push to update the docs to use TWEAK more than BUILD. The idea being that 9 times out of 10 it's want you want. And of that other time you probably want BUILD and THEN you might want to write a new method.

以上是实例化一个Raku类,并在构造函数中更新一个实例变量的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>