MODULE化

本ページには広告が含まれています。

関連する機能(メソッド)やデータ(プロパティ)をひとつのグループとしてまとめたものをモジュールと言います。モジュール化することでプログラムの構造化、利用性や保守性を高めることができます。

構文
MODULE モジュール名
  CONST 変数
  PUBLIC 変数
  DIM 変数
  PROCEDURE モジュール名
  PROCEDURE 関数名( )
  FUNCTION 関数名( )
ENDMODULE

CLASS クラス名
  CONST 変数
  PUBLIC 変数
  DIM 変数
  PROCEDURE クラス名
  PROCEDURE 関数名( )
  FUNCTION 関数名( )
ENDCLASS
引数
戻り値

モジュールとは

モジュールとはプログラムにおいて特定の機能を持ったひとまとまりの構成要素(部品)のことを指します。

モジュールは関数をMODULE-ENDMODULEもしくはCLASS-ENDCLASSで囲むことで定義することができます。MODULEモジュールCLASSクラスで2種類の書き方がありますが、どちらも動作としては全く同じものとなります。

クラスというと他の言語ではインスタンス生成をしたりできますが、UWSCでのクラスはあくまで名前空間を管理するためのものです。CLASS-ENDCLASSで定義するとクラス化と紛らわしいので当サイトでは基本的にMODULE-ENDMODULEでモジュールを定義します。

モジュール内に関数を作る方法については関数の定義を参考にしてください。

名前空間

名前空間とは、識別子(変数名や関数名)の衝突(重複)を防ぎ、コードやデータを整理・管理するための仕組みのことです。

具体的な例を出すと、当サイトでは数値を負の方向に丸める関数としてfloor関数 (自作関数)を定義しています。これとは別にDecimalモジュール (自作関数)にもfloor関数を定義していますが、関数が重複しているというエラーは発生しません。

これは名前空間を分けていることでそれぞれの関数を区別できるためで、PROCEDURE-FENDFUNCTION-FENDで定義した関数とMODULE化で定義したモジュール内の関数では呼び出し方が異なります。

モジュールで定義した関数の呼び出し方法は関数を呼び出す方法で記述しますが、通常の関数とモジュール内で定義した関数は簡潔に書くと以下のように呼び出し方に違いがあります。

UWSC
PRINT floor(arg)          // 関数名
PRINT Decimal.floor(args)  // モジュール.関数名

モジュール定義のメリット

データと処理のカプセル化
状態(プロパティ)と機能(メソッド)を一つのまとまりとして管理することができます。
状態の保持
前回の処理結果や設定を保持することができます。
名前空間の整理
宣言された変数や関数が参照できるスコープがモジュール内に収まるのでモジュール内外で重複する変数名・関数名をつけることができ、名前の衝突が防げます。
保守性の向上
関連するコードがモジュール内にまとめられているので、機能を修正する際変更の影響を受ける範囲をモジュール内単位で局所化できます。バグ修正や機能拡張が容易となります。

例えばPythonでは、数学計算用の関数を集めたmathモジュール、日付や時間を扱うdatetimeモジュールなどがあります。

モジュールは入れ子(ネスト)することはできませんが、関数名に.(ピリオド)をつけることで階層化したように見せる書き方はできます。

UWSC
MODULE Cipher
	MODULE Caesar
		FUNCTION encode()
			RESULT = ""
		FEND
		FUNCTION decode()
			RESULT = ""
		FEND
	ENDMODULE
ENDMODULE

Cipherモジュール (自作関数)では、モジュール名がCipher、関数名にCaesar.encodeCaesar.decodeで入れ子したような書き方をしています。

このような書き方をすることでCipher.Caesar.encode()Cipher.Caesar.decode()というメソッドが使えるようになります。

UWSC
MODULE Cipher
	FUNCTION Caesar.encode()
		RESULT = ""
	FEND
	FUNCTION Caesar.decode()
		RESULT = ""
	FEND
ENDMODULE

ただ注意が必要なのはあくまでCaesar.encodeCaesar.decodeというひとかたまりで関数名で.がモジュール名とメソッドの区切りを表しているわけではないので、このピリオドで区切りWITH文で書くということはできません。

UWSC
WITH Cipher.Caesar
	PRINT .encode()
	PRINT .decode()
ENDWITH

モジュール名と関数名を分けることはできます。

UWSC
WITH Cipher
	PRINT .Caesar.encode()
	PRINT .Caesar.decode()
ENDWITH

関数を呼び出す方法

関数を呼び出す例として以下のプログラムを使います。モジュールの内部と外部にalert関数が定義されていて、それぞれを内部・外部から呼び出す方法について解説します。

UWSC
MODULE myClass
	PROCEDURE alert()
		MSGBOX("モジュール内の関数")
	FEND
ENDMODULE

PROCEDURE alert()
	MSGBOX("モジュール外の関数")
FEND

モジュール内部から関数を呼び出す方法

モジュール内部から呼び出すのでmyClassモジュールにtest関数を定義し、そのtest関数から呼び出す例を記述します。

内部から内部の関数

モジュール内部から内部に定義した関数を呼び出すには、呼び出す関数名をそのまま記述します。

以下は、myClassモジュールのtest関数からモジュール内のalert関数を呼び出す例です。

UWSC
myClass.test()

MODULE myClass
	PROCEDURE test()
		alert()
	FEND
	PROCEDURE alert()
		MSGBOX("モジュール内の関数")
	FEND
ENDMODULE

PROCEDURE alert()
	MSGBOX("モジュール外の関数")
FEND
結果
プレーンテキスト
モジュール内の関数

THIS.関数名と記述することでモジュール内部の関数と明示することもできます。

UWSC
myClass.test()

MODULE myClass
	PROCEDURE test()
		THIS.alert()
	FEND
	PROCEDURE alert()
		MSGBOX("モジュール内の関数")
	FEND
ENDMODULE

PROCEDURE alert()
	MSGBOX("モジュール外の関数")
FEND
結果
プレーンテキスト
モジュール内の関数

モジュール内部に標準関数と同じ関数を定義している場合も同様に、THIS.関数名と記述することでモジュール内部の関数を呼び出すことができます。

以下はmyClassモジュールに2000年1月1日からの秒数(ミリ秒を含む)を返すGETTIME関数を定義し、それを呼び出しています。

UWSC
MSGBOX(myClass.test())

MODULE myClass
	FUNCTION test()
		RESULT = THIS.GETTIME()
	FEND
	FUNCTION GETTIME()
		RESULT = GLOBAL.GETTIME() + G_TIME_ZZ / 1000
	FEND
ENDMODULE
結果
プレーンテキスト
811631575.18
内部から外部の関数

モジュール内部から外部に定義した関数を呼び出すには、GLOBAL.関数名と記述します。

UWSC
myClass.test()

MODULE myClass
	PROCEDURE test()
		GLOBAL.alert()
	FEND
	PROCEDURE alert()
		MSGBOX("モジュール内の関数")
	FEND
ENDMODULE

PROCEDURE alert()
	MSGBOX("モジュール外の関数")
FEND
結果
プレーンテキスト
モジュール外の関数

モジュール内部に標準関数と同じ関数を定義している場合も同様に、GLOBAL.標準関数名と記述することで標準関数を呼び出すことができます。

以下はmyClassモジュール内からUWSCの標準関数であるGETTIMEを呼び出しています。

UWSC
MSGBOX(myClass.test())

MODULE myClass
	FUNCTION test()
		RESULT = GLOBAL.GETTIME()
	FEND
	FUNCTION GETTIME()
		RESULT = GLOBAL.GETTIME() + G_TIME_ZZ / 1000
	FEND
ENDMODULE
結果
プレーンテキスト
811631575

モジュール外部から関数を呼び出す方法

外部から内部の関数

モジュール外部から内部に定義した関数を呼び出すには、モジュール名.関数名と記述します。

UWSC
myClass.alert()

MODULE myClass
	PROCEDURE alert()
		MSGBOX("モジュール内の関数")
	FEND
ENDMODULE

PROCEDURE alert()
	MSGBOX("モジュール外の関数")
FEND
結果
プレーンテキスト
モジュール内の関数
外部から外部の関数

モジュール外部から外部の関数を呼び出すことは通常の関数を呼び出すのと同じなので、呼び出す関数名のみを記述します。

UWSC
alert()

MODULE myClass
	PROCEDURE test()
		GLOBAL.alert()
	FEND
	PROCEDURE alert()
		MSGBOX("モジュール内の関数")
	FEND
ENDMODULE

PROCEDURE alert()
	MSGBOX("モジュール外の関数")
FEND
結果
プレーンテキスト
モジュール外の関数

使い方

モジュール内にある変数・関数・モジュール名を呼び出すには以下のように書きます。

UWSC
モジュール名.変数
モジュール名.モジュール名
モジュール名.関数名([引数], ...)

CONSTまたはPUBLICで宣言されたものは、モジュール名.変数で外部からも呼び出すことができます。

自モジュール内の変数、関数には自モジュールを示すTHIS.を付けてのアクセス可。

モジュール内からモジュール外関数を使う場合にGLOBAL.関数名にて明示可。

DIMで宣言されたものは、外部からアクセスすることはできません。

モジュール内の関数から同一モジュール内の関数を呼び出すときモジュール名は省略できます。

コンストラクタ

モジュール名と同じ関数は コンストラクタ として機能します。コンストラクタはインスタンス生成時に自動的に呼び出されるメソッドで、メンバを初期化するときによく使われます。モジュール内のすべての関数で共通する初期処理を記述する使い方もできます。

以下はclassNameというモジュール名で、同一のメソッドが実行されコンストラクタという文字列が出力されます。関数1と関数2はコンストラクタではないので出力されません。

UWSC
MODULE className
	PROCEDURE className
		PRINT "コンストラクタ"
	FEND
	PROCEDURE func1()
		PRINT "関数1"
	FEND
	PROCEDURE func2()
		PRINT "関数2"
	FEND
ENDMODULE
結果
プレーンテキスト
コンストラクタ

モジュールの書き方

以下のプログラムは、Pythonのmathモジュールの一部をUWSCで書いてみた例です。

UWSC
PRINT math.pi
PRINT math.e
PRINT math.tau
PRINT math.fabs(-4)
PRINT math.factorial(5)

MODULE math
	// 円周率π
	CONST pi = 3.14159265358979323846
	// 自然対数e
	CONST e = 2.71828182845904523536
	// τ(τ=2π)
	CONST tau = THIS.pi * 2
	// 引数の絶対値を返す
	FUNCTION fabs(x)
		RESULT = ABS(x)
	FEND
	// 引数の階乗を返す
	FUNCTION factorial(x)
		IF x <> ABS(INT(x)) THEN RESULT = ERR_VALUE
		IFB x = 0 OR x = 1 THEN
			RESULT = 1
		ELSE
			RESULT = x * factorial(x - 1)
		ENDIF
	FEND
ENDMODULE

関連記事

QuotedPrintableモジュール (自作関数)
文字列をQuoted-Pintableにエンコード・デコードします。Quoted-Printableとは、電子メールの送受信の際に用いられるデータの変換方式のひとつで、本文に用いられる8ビット文字を7ビットのデータであるASCIIコードに変換する方式のことです。
Base64モジュール (自作関数)
文字列をBASE64にエンコード・デコードします。BASE64とは、バイナリデータを一定の規則に基づいてテキスト(文字)データに置き換える変換方式の一つで、64種類の英数字のみを用いてデータを表現する方式。 電子メールの添付ファイル(MIME)などでよく用いられます。
Cipherモジュール (自作関数)
引数に指定した文字列をシーザー暗号・ROT13・ヴィジュネル暗号・XOR暗号の4種類に暗号化または復号します。
Morseモジュール (自作関数)
引数に指定した文字列をモールス信号、またはモールス信号を文字列に変換します。