18

Perl6 でカスタム アクセサ メソッドを作成するにはどうすればよいですか?

このクラスがある場合:

class Wizard {
    has Int $.mana is rw;
}

私がすることができます:

my Wizard $gandalf .= new;
$gandalf.mana = 150;

記法をあきらめずに、Perl6 クラスのセッターに小さなチェックを追加したいとしましょう$gandalf.mana = 150;(つまり、これを書きたくない : $gandalf.setMana(150);)。負のマナを設定しようとすると、プログラムは停止するはずです。どうすればいいですか?Perl6 のドキュメントには、カスタム アクセサーを作成できると記載されているだけで、その方法については記載されていません。

4

2 に答える 2

19

Rakudo の最近のバージョンでは、UInt正の値に制限するという名前のサブセットがあります。

class Wizard {
  has UInt $.mana is rw;
}

このようなことが必要な場合に、あなたが急いで立ち往生しないように。これがどのように定義されているかです:
( は省略できますが、Rakudo ソースからの実際の行myをお見せしたかったのです)

my subset UInt of Int where * >= 0;

これを行うこともできます:

class Wizard {
  has Int $.mana is rw where * >= 0;
}

制約* >= 0内のは、 Callableを作成する簡単な方法に過ぎないことを指摘したいと思います。where

where制約として次のいずれかを指定できます。

... where &subroutine # a subroutine that returns a true value for positive values
... where { $_ >= 0 }
... where -> $a { $a >= 0 }
... where { $^a >= 0 }
... where $_ >= 0 # statements also work ( 「$_」 is set to the value it's testing )

(ゼロにならないようにしたい場合は、 or... where &prefix:<?>のように綴ったほうがよいものを使用することもできます)... where ?*... where * !== 0


コードを使用している人々に迷惑をかけたい場合は、これを行うこともできます。

class Wizard {
  has UInt $.mana is rw where Bool.pick; # accepts changes randomly
}

クラス内のすべての値を集約して見て、値が「意味を成す」ことを確認したい場合は、さらに多くの作業を行う必要があります。
(実装についての知識も必要になる場合があります)

class Wizard {
  has Int $.mana; # use . instead of ! for better `.perl` representation

  # overwrite the method the attribute declaration added
  method mana () is rw {
    Proxy.new(
      FETCH => -> $ { $!mana },
      STORE => -> $, Int $new {
        die 'invalid mana' unless $new >= 0; # placeholder for a better error
        $!mana = $new
      }
    )
  }
}
于 2015-07-28T18:13:35.470 に答える