我似乎很难理解如何正确使用 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.
你有两种方法来处理这个问题。您可以将它们设置为TWEAK或BUILD,或者您可以将属性添加到属性中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,但所有初始设置都已完成(构建或自动绑定到公共属性,以及所有默认值,并保证所需值存在)。你只是有机会做一些最后一秒的调整。