量産型エンジニアの憂鬱

きっと僕は何物にもなれない。

Perl6でprivateなメンバにコンストラクタで値を渡したい

※ 追記あり

Perl6でprivateなメンバを作ったときに、コンストラクタで値を渡せなくてちょっとハマったのでメモ。

publicなメンバを設定する場合、

メンバ変数の $ の後に . をつけることで、アクセッサが自動的にできます。
インスタンスからメンバ名でアクセスできるようになります。
また、デフォルトコンストラクタでは、名前付き引数としてpublicなメンバに値を渡してやることができます。

publicなフィールドのみ持つクラスを作る場合はめっちゃスッキリ。
Pythonの namedTuple とかそんな感じで使えますね。

さて、メンバをprivateにしたい場合はどうするのか。
変数の . を ! に変更することで、 private なメンバになります。

この場合、アクセッサは自分で記述する必要があります。
また、デフォルトコンストラクタでは値を渡すことができません。

じゃあ、コンストラクタをオーバライドしてみましょう。

これでもダメでした。
blessの時点で値が入ってこないみたい。

それなら、blessした後に private なメソッドを介して値を渡してやればいいんじゃないか。

イケました。
private なメソッドはメソッド名の前に ! をつけます。
インスタンスから実行しようとしてもちゃんと syntax error になりました。

アクセッサをオーバライドする

アクセッサをオーバーライドしてdieするなどして、アクセスできなくしちゃう方法もあります。
この場合、コンストラクタはデフォルトでいいので便利かも。
クラス内からメンバ変数にアクセスする場合に . でアクセスするとオーバライドしたメソッドが呼び出されてしまうので、 ! でアクセスするのが注意点。


[2016/11/06追記]

BUILDで書く

ご指摘いただきました。公式でちゃんと書かれてますね。

submethod BUILD で private なフィールドに値を設定できます。
ご指摘&URLのご紹介ありがとうございます。
newをオーバーライドするのは、どうしても固定長引数にしたい時など限定的な場合のみにした方がよさそうですね。