チェスの状況をモデル化するための小さなクラスのセットで、位置を表すクラスを作成したいと思いました。しかし、システムが同じ位置に対して複数のオブジェクトを作成しないように、有効な64の位置のみを作成(およびエクスポート)し、この後コンストラクターをプライベートにしたいと思いました。基本的にシングルトンですが、1=64です。64トン。すこし。
考えられる使用法:
use Positions; # exports positions
my $pos = e4;
# something happens...
do_foo() if $pos == d5;
do_bar() if $pos->row == 8;
私のソリューションは私が望むように機能しますが、それは一種のエレガントで過剰に設計されているように感じます。
基本:
package Position;
use Moo;
has column => (is => 'ro');
has row => (is => 'ro');
has name => (is => 'lazy');
sub _build_name {
my $self = shift;
return $self->column . $self->row;
}
sub to_string { shift->name }
# ...
isa
クラスユーザーに位置オブジェクトをインスタンス化させたくないので、で有効な列または行のエラーチェックはありません。次に、エクスポートについて説明します。
# prepare 64 positions
my %position;
foreach my $col ('a' .. 'h') {
foreach my $row (1 .. 8) {
# build
my $name = "$col$row";
my $pos = Cherl::Position->new(column => $col, row => $row);
# remember
$position{$name} = $pos;
}
}
# export
sub import {
my $class = shift;
my $caller = caller;
# magic!
no strict 'refs';
for my $name (sort keys %position) {
*{$caller . '::' . $name} = sub { $position{$name} };
}
}
# make it private
sub BUILDARGS {
my ($class, @args) = @_;
die 'private' unless +(caller 1)[0] eq __PACKAGE__;
return $class->SUPER::BUILDARGS(@args);
}
私が考えることができる代替案
column
sとsのエラーチェックを追加し、2つの位置の名前が等しい場合にtrueを返すようrow
に演算子をオーバーロードして、位置を適切に比較します。==
このシナリオで同じ位置に多数のオブジェクトを作成するのは少し怖いですが、これは初期の最適化かもしれません。
したがって、問題は、このクラスを(Mooを使用して)設計するためのより良い方法があるかどうかです。TIA!:)