2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?