コンストラクタの定義
コンストラクタは、次のようなコマンドで定義します。 Constructor <パラメータリスト> <実装> <パラメータリスト>は、Type 型の配列で、<実装>はスクリプトブロックです。実際に作ってみましょう。
PS> New-Class Class3 { >> Constructor ([string]) { >> $args[0].Message = $args[1] >> } >> Field public string Message >> } >> |
||
NameSpace | Name | BaseType |
———– | —- | ———- |
Class3 | System.Object |
Class3 は、string 型のパブリックフィールド「Message」を持ち、そのコンストラクタは、string 型の引数を受け取って、それを Message に代入します。ここで、$args[0] には、このクラスによって作られるオブジェクトのインスタンスが代入されており、$args[1..] には、コンストラクタに渡される引数が代入されています。今回の場合、引数は一つだけですので、$args.Length は 2 です。 試してみましょう。
PS> $o.Message
Hello World!
ちゃんと Message に「Hello World!」が代入されています。
Private なフィールドへのアクセス
New-Class.ps1 は、PowerShell でクラスを記述しやすくするために、コンストラクタやメソッドなどをスクリプトブロックで実装する仕様になっています。 すると、ここに一つ問題点が出てきます。それは、PowerShell のスクリプトブロックというのは、あくまでオブジェクトから見れば「よそ者」であるということです。したがって、Private なメンバにシームレスにアクセスすることができません。例えば、次のようにコンストラクタ中で Private なフィールドへ値を代入しようとすると、エラーが発生します。
PS> New-Class Class4 { >> Constructor ([string]) { >> $args[0].Message = $args[1] >> } >> Field private string Message >> } >> |
||
NameSpace | Name | BaseType |
——— | —- | ——– |
Class4 | System.Object | |
PS> $o = New-Object Class4('Hello World!') New-Object : "1" 個の引数を指定して ".ctor" を呼び出し中に例外が発生しました: "このオブジェクトにプロパティ ‘Message’ が見つかりません。プロパティが存在し、設定可能なことを確認してください。" 発生場所 行:1 文字:16 + $o = New-Object <<<< Class4(‘Hello World!’) |
そのため、次のような冗長な書き方をしなくてはなりません。
PS> New-Class Class5 { >> Constructor ([string]) { >> $args[0].GetType().GetField('Message', ('NonPublic', 'Instance')).SetValue($args[0], $args[1]) >> } >> Field private string Message >> } >> |
||
NameSpace | Name | BaseType |
——— | —- | ——– |
Class5 | System.Object | |
PS> $o = New-Object Class5('Hello World!') PS> $o.GetType().GetField('Message', ('NonPublic', 'Instance')).GetValue($o) Hello World! |
何かいい方法がないか模索中です。
複数のコンストラクタ
コンストラクタはもちろん複数作ることができます。次の例の Class6 は 3 通りの方法でインスタンス化できます。引数が必要ない時、「Constructor {}」としたくなりますが、「Constructor @() {}」と、空の配列を渡すのを忘れないようにしてください。
>> Constructor @() {}
>> Constructor ([string]) {}
>> Constructor ([string], [int]) {}
>> }
>>
PS> $o = New-Object $c
PS> $o = New-Object $c('Hello World!')
PS> $o = New-Object $c('Hello World!', 100)