PowerShellで、class構文を使わずに、classを定義する



PowerShell 5.0からはclassキーワードが使えますが、PowerShell 4.0ではclassキーワードを使えないので、以下のようにやっていました。
PowerShell 2.0でも動作を確認しています。

Person.psm1
function getInstance ($name) {
    $instance = New-Object -TypeName psobject
    # プロパティーを定義
    $instance | Add-Member -MemberType NoteProperty -Name "name" -Value $name
    # メソッドを定義
    $instance | Add-Member -MemberType ScriptMethod -Name "getName" -Value {getName}
    $instance | Add-Member -MemberType ScriptMethod -Name "setName" -Value {
        param($name)
        setName $name
    }
    return $instance
}

function getName () {
    return $this.name
}

function setName ($name) {
    $this.name = $name
}

main.ps1
$env:PSModulePath += ":classes"
Import-Module Person -Prefix Person.
$person1 = Person.getInstance "John"
$person2 = Person.getInstance "Paul"
$person1.setName("Lennon")
$person1.getName()
$person2.getName()

下記のディレクトリー構成で配置しました。
.
├── classes
│   └── Person
│       └── Person.psm1
├── main.ps1

Person.psm1は、classの定義ファイルで、外部ファイルとして作成しました。

getInstanceが、インスタンスを生成、初期化して返すfunctionで、コンストラクターみたいなものです。

インスタンスはpsobjectとして作成し、Add-Memberで、プロパティーとメソッドを追加しました。

上の例では、プロパティーとして、名前を表現するname、メソッドとして、ゲッター(getName)とセッター(setName)を定義しました。

インスタンスのメンバーには、$thisを介してアクセスできます。

プライベートメソッドの作り方はわからなかったです。命名規則でやるしかない?

main.ps1は、classを利用するスクリプトです。

Person.psm1をPrefix付きで読み込んで、Person.getInstanceのようにアクセスできるようにしました。

getInstanceでインスタンスを初期化、取得し、getNameメソッド、setNameメソッドを呼んでいます。

実行すると、予期した動きとなりました。

$ pwsh main.ps1
Lennon
Paul

コメント

このブログの人気の投稿

PowerShell 6で、Shift_JISのCSVをImport-Csvで読み込んだら文字化けした

Windowsで、特定のユーザーに特定のサービスの再起動を許可する

PowerShellでイベントログを取得する時、「指定した選択条件に一致するイベントが見つかりませんでした。」が煩わしいのでcatchする