perl6 上的单例实现
Singleton implementation on perl6
我在Rosetta代码上看了下面的代码http://rosettacode.org/wiki/Singleton#Perl_6
它在 Perl6 中实现了 Singleton
class Singleton {
has Int $.x is rw;
# We create a lexical variable in the class block that holds our single instance.
my Singleton $instance = Singleton.bless; # You can add initialization arguments here.
method new {!!!} # Singleton.new dies.
method instance { $instance; }
}
my $a=Singleton.bless(x => 1);
my $b=Singleton.bless(x=> 2);
say $a.x;
say $b.x;
#result
# 1
# 2
但似乎使用此实现我可以创建相同 class 的两个实例,请参见上面的示例,
是否有一个选项可以防止仅对同一 class 的一个实例实施?
Perl 以提供多种做事方式而自豪,让您可以选择适合您的口味和手头应用程序的方式。我这样说是为了强调这是一种简单但可靠、希望不言自明的方式 - 我不会将其作为 "the best" 提出,因为这取决于您的情况。
#!/usr/bin/env perl6
class Scoreboard {
has Str $.home-team ;
has Str $.away-team ;
has Int $.home-score = 0 ;
has Int $.away-score = 0 ;
my Scoreboard $instance;
method new(*%named) {
return $instance //= self.bless(|%named) ;
}
multi method goal($team where * eq $!home-team, Int :$points = 6) {
$!home-score += $points
}
multi method goal($team where * eq $!away-team, Int :$points = 6) {
$!away-score += $points
}
method Str {
"At this vital stage of the game " ~
do given $!home-score <=> $!away-score {
when More {
"$!home-team are leading $!away-team, $!home-score points to $!away-score"
}
when Less {
"$!home-team are behind $!away-team, $!home-score points to $!away-score"
}
default {
"the scores are level! $!home-score apeice!"
}
}
}
}
my $home-team = "The Rabid Rabbits";
my $away-team = "The Turquoise Turtles"; # Go them turtles!
my $scoreboard = Scoreboard.new( :$home-team , :$away-team );
$scoreboard.goal($home-team, :4points) ;
say "$scoreboard";
$scoreboard.goal($away-team) ;
say "$scoreboard";
my $evil_second_scoreboard = Scoreboard.new;
$evil_second_scoreboard.goal($home-team, :2points) ;
say "$evil_second_scoreboard";
这会产生;
At this vital stage of the game The Rabid Rabbits are leading The Turquoise Turtles, 4 points to 0
At this vital stage of the game The Rabid Rabbits are behind The Turquoise Turtles, 4 points to 6
At this vital stage of the game the scores are level! 6 apeice!
这会覆盖默认的 new(通常由 class Mu 提供)并保留对我们自己的引用(即这个对象)在私有 class 数据中。对于私有 class 数据,我们使用用 my 声明的词法范围标量。 //
是 .defined
的运算符形式。因此,在第一个 运行 上,我们调用 bless 分配对象并初始化属性,然后将其赋值给 $instance
。在对 new 的后续调用中,$instance
被定义并立即返回。
如果要防止有人直接调用bless,可以加上;
method bless(|) {
nextsame unless $instance;
fail "bless called on singleton Scoreboard"
}
这将确保只有第一次调用有效。
我在Rosetta代码上看了下面的代码http://rosettacode.org/wiki/Singleton#Perl_6 它在 Perl6 中实现了 Singleton
class Singleton {
has Int $.x is rw;
# We create a lexical variable in the class block that holds our single instance.
my Singleton $instance = Singleton.bless; # You can add initialization arguments here.
method new {!!!} # Singleton.new dies.
method instance { $instance; }
}
my $a=Singleton.bless(x => 1);
my $b=Singleton.bless(x=> 2);
say $a.x;
say $b.x;
#result
# 1
# 2
但似乎使用此实现我可以创建相同 class 的两个实例,请参见上面的示例,
是否有一个选项可以防止仅对同一 class 的一个实例实施?
Perl 以提供多种做事方式而自豪,让您可以选择适合您的口味和手头应用程序的方式。我这样说是为了强调这是一种简单但可靠、希望不言自明的方式 - 我不会将其作为 "the best" 提出,因为这取决于您的情况。
#!/usr/bin/env perl6
class Scoreboard {
has Str $.home-team ;
has Str $.away-team ;
has Int $.home-score = 0 ;
has Int $.away-score = 0 ;
my Scoreboard $instance;
method new(*%named) {
return $instance //= self.bless(|%named) ;
}
multi method goal($team where * eq $!home-team, Int :$points = 6) {
$!home-score += $points
}
multi method goal($team where * eq $!away-team, Int :$points = 6) {
$!away-score += $points
}
method Str {
"At this vital stage of the game " ~
do given $!home-score <=> $!away-score {
when More {
"$!home-team are leading $!away-team, $!home-score points to $!away-score"
}
when Less {
"$!home-team are behind $!away-team, $!home-score points to $!away-score"
}
default {
"the scores are level! $!home-score apeice!"
}
}
}
}
my $home-team = "The Rabid Rabbits";
my $away-team = "The Turquoise Turtles"; # Go them turtles!
my $scoreboard = Scoreboard.new( :$home-team , :$away-team );
$scoreboard.goal($home-team, :4points) ;
say "$scoreboard";
$scoreboard.goal($away-team) ;
say "$scoreboard";
my $evil_second_scoreboard = Scoreboard.new;
$evil_second_scoreboard.goal($home-team, :2points) ;
say "$evil_second_scoreboard";
这会产生;
At this vital stage of the game The Rabid Rabbits are leading The Turquoise Turtles, 4 points to 0
At this vital stage of the game The Rabid Rabbits are behind The Turquoise Turtles, 4 points to 6
At this vital stage of the game the scores are level! 6 apeice!
这会覆盖默认的 new(通常由 class Mu 提供)并保留对我们自己的引用(即这个对象)在私有 class 数据中。对于私有 class 数据,我们使用用 my 声明的词法范围标量。 //
是 .defined
的运算符形式。因此,在第一个 运行 上,我们调用 bless 分配对象并初始化属性,然后将其赋值给 $instance
。在对 new 的后续调用中,$instance
被定义并立即返回。
如果要防止有人直接调用bless,可以加上;
method bless(|) {
nextsame unless $instance;
fail "bless called on singleton Scoreboard"
}
这将确保只有第一次调用有效。