实例化一个 Raku class,并在构造函数中更新一个实例变量
Instantiate a Raku class, and update an instance variable in the constructor
我似乎很难理解如何在 Raku 中正确使用 classes。
我正在尝试创建一个 'Database' class,我将在整个 cro 应用程序中使用它。但是我似乎不明白如何在对象构造(BUILD?)时处理设置实例变量。
下面的 class 显示了我在调用它时遇到的问题的示例:
通话中:
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
我的Class:
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;
}
}
所以在我的 class 构造函数中,我想为数据库 dsn 传递一个命名的 arg。
在我打算连接的新方法中,将实例变量设置为连接句柄。
在这个例子中,我使用一个简单的整数 (foo) 作为测试。
到目前为止,我发现 the docs here 不包含此类模式的示例,除了 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.
如有任何帮助,我们将不胜感激!
只有具有 public 访问器的属性(即 .
twigil)会自动设置为 bless
。
你有两种方法来处理这个问题。您可以将它们设置为 TWEAK
或 BUILD
,或者您可以将属性 is built
添加到属性中以自动为您完成此操作。在这种情况下,属性 is built
可能是最简单的,只需说 has Int $!foo is built = 0
。但值得扩展其他选项:
如果您包含 BUILD
方法,您将自行负责所有设置。这意味着 public 和 私有属性。但是你可以通过巧妙地命名参数来让你的生活更轻松:
method BUILD (:$!dsn, :$!dbh, :$!foo) { }
实际上就是这样。签名将传入值绑定到 $!dsn
等,这当然会为整个对象实例设置它们。当然,你也可以在这里做更奇葩的事情。无论如何,在 BUILD
之后,还会进行一些额外的检查。 (1)如果你不设置$!dsn
,因为你有is required
,就会报错。 (2) 如果你最终没有设置$!foo
或$!dbh
,他们将收到他们的默认值。
使用 TWEAK
,您将获得与使用 BUILD
相同的参数,但所有初始设置都已完成(构建或自动绑定到 public 属性,和所有默认值,并保证所需的值存在)。您只是有机会进行一些最后的调整。
我似乎很难理解如何在 Raku 中正确使用 classes。
我正在尝试创建一个 'Database' class,我将在整个 cro 应用程序中使用它。但是我似乎不明白如何在对象构造(BUILD?)时处理设置实例变量。
下面的 class 显示了我在调用它时遇到的问题的示例:
通话中:
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
我的Class:
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;
}
}
所以在我的 class 构造函数中,我想为数据库 dsn 传递一个命名的 arg。 在我打算连接的新方法中,将实例变量设置为连接句柄。
在这个例子中,我使用一个简单的整数 (foo) 作为测试。
到目前为止,我发现 the docs here 不包含此类模式的示例,除了 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.
如有任何帮助,我们将不胜感激!
只有具有 public 访问器的属性(即 .
twigil)会自动设置为 bless
。
你有两种方法来处理这个问题。您可以将它们设置为 TWEAK
或 BUILD
,或者您可以将属性 is built
添加到属性中以自动为您完成此操作。在这种情况下,属性 is built
可能是最简单的,只需说 has Int $!foo is built = 0
。但值得扩展其他选项:
如果您包含 BUILD
方法,您将自行负责所有设置。这意味着 public 和 私有属性。但是你可以通过巧妙地命名参数来让你的生活更轻松:
method BUILD (:$!dsn, :$!dbh, :$!foo) { }
实际上就是这样。签名将传入值绑定到 $!dsn
等,这当然会为整个对象实例设置它们。当然,你也可以在这里做更奇葩的事情。无论如何,在 BUILD
之后,还会进行一些额外的检查。 (1)如果你不设置$!dsn
,因为你有is required
,就会报错。 (2) 如果你最终没有设置$!foo
或$!dbh
,他们将收到他们的默认值。
使用 TWEAK
,您将获得与使用 BUILD
相同的参数,但所有初始设置都已完成(构建或自动绑定到 public 属性,和所有默认值,并保证所需的值存在)。您只是有机会进行一些最后的调整。