LoginSignup
2
1

More than 5 years have passed since last update.

HSPでモジュールの継承・ポリモーフィズム(多態性)っぽいもの

Last updated at Posted at 2018-02-16

HSPでポリモーフィズムっぽい何かで他言語におけるポリモーフィズムみたいな書き方ができることを確認したので、例として15分でわかる かんたんオブジェクト指向の(J)から(N)位までのソースコードを移植・実装してみました。

純粋な継承はできないけど、継承されるモジュール側で十分にお膳立て(superメソッド・オーバーライドしたいモジュール関数の設定)をしっかりしてあげれば実用範囲で使用可能なのかな?
2018/2/18 追記: 継承先から継承元のモジュール変数にアクセスすることについて追記。

動作

HSP部屋

実装 (コメントまま)

#runtime "hsp3cl"

// getFullName以外をPersonに実装
#module Person givenName, familyName, age, getFullNamePtr

    #modinit str initialGivenName, str initialFamilyName, int initialAge
        super@Person thismod, initialGivenName, initialFamilyName, initialAge
        getFullNamePtr = *getFullNameSub
    return

    #modfunc local super str initialGivenName, str initialFamilyName, int initialAge
        givenName = initialGivenName
        familyName = initialFamilyName
        age = initialAge
    return

    *getFullNameSub
        return "null" // 無意味な値を返す

    #modcfunc getFullName
        gosub getFullNamePtr
        return refstr

    #modcfunc getGivenName
        return givenName

    #modfunc setGivenName str newGivenName
        givenName = newGivenName
    return

    #modcfunc getFamilyName
        return familyName

    #modfunc setFamilyName str newFamilyName
        familyName = newFamilyName
    return

    #modcfunc getAge
        return age

    #modfunc setAge int newAge
        age = newAge
    return
#global

// Personを継承してWesternPersonを作る
// (extendsは継承を表すときに使われることが多いキーワード)
#module WesternPerson givenName, familyName, age, getFullNamePtr
    // WesternPersonのコンストラクタ
    #modinit str initialGivenName, str initialFamilyName, int initialAge
        // 継承元のPersonのコンストラクタを呼んで初期化
        // (superは継承元のクラスを表すときに使われることが多いキーワード)
        super@Person thismod, initialGivenName, initialFamilyName, initialAge
        getFullNamePtr = *getFullNameSub
    return

    // PersonではなくここでgetFullNameを実装
    *getFullNameSub
        // return getGivenName(thismod) + " " + getFamilyName(thismod) // 名 姓
        return givenName@Person + " " + familyName@Person // 名 姓
#global

// Personを継承してEasternPersonを作る
#module EasternPerson givenName, familyName, age, getFullNamePtr
    // EasternPersonのコンストラクタ
    #modinit str initialGivenName, str initialFamilyName, int initialAge
        // 継承元のPersonのコンストラクタを呼んで初期化
        super@Person thismod, initialGivenName, initialFamilyName, initialAge
        getFullNamePtr = *getFullNameSub
    return

    // PersonではなくここでgetFullNameを実装
    *getFullNameSub
        //return getFamilyName(thismod) + " " + getGivenName(thismod) // 姓 名
        return familyName@Person + " " + givenName@Person // 姓 名
#global

newmod _westernPerson, WesternPerson, "Albert", "Einstein", 26
newmod _easternPerson, EasternPerson, "信長", "織田", 47

mes getFullName(_westernPerson) // Albert Einstein
mes getFullName(_easternPerson) // 織田 信長

newmod people, WesternPerson, "Albert", "Einstein", 26
newmod people, EasternPerson, "信長", "織田", 47
newmod people, WesternPerson, "Isaac", "Newton", 43
newmod people, EasternPerson, "秀吉", "豊臣", 61
newmod people, WesternPerson, "Galileo", "Galilei", 46
newmod people, EasternPerson, "家康", "徳川", 73

// peopleの要素を一つずつpersonに代入して実行されるfor-eachループ
foreach people
    mes getFullName(people(cnt))
loop

// Personクラス
newmod _person, Person, "Albert", "Einstein", 26

mes getFullName(_person) // null

余談

ラベルを関数ポインタと見立ててモジュール変数に登録をしています。
gosubするまでは良いのですが、ラベルの名前空間?が呼び出されるモジュールと異なる場合、ダイレクトにモジュール変数を触ることができないため注意が必要です。
⇒ 継承元の名前空間に変数名を合わせれば可能なようです。ソースコードに直接追記しました。

あとはHSP3Dishではやはりgosub周りで挙動がおかしくなる様子。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1