Entering Passive Mode

カテゴリ 'Perl' の記事
< 1 2 3 4 5 6 7 8... >

プロパティと言う概念

一部の高級言語には、プロパティと言う概念がある。
プロパティは、setter と getter を
特別な構文でカプセル化したものだ。

    Rectangle rect = new Rectangle();
    rect.width = 100;
    int value = rect.width;

C# や VB など、Microsoft 系のユーザにはおなじみだが、
Java や C++、Perl などには、それらの概念がない。

まとめて実装

さて、今までの考察を盛り込み、
細かい問題点を整理していき、
モジュールとしてまとめてみよう。

========== EncoderHandle.pm ==========

# 独自クラス。
package EncoderHandle;

# Perl 5.6 以上を要求する。
require v5.6.0;

インタフェースの統一

Encode, Jcode, jcode.pl はそれぞれ呼び出し規則が異なる。

今日はそれを吸収する仕組みを作ろう。
クラスレベルでインタフェースを統一する場合、
ラッパークラスを作るのが一般的。(Adapter パターン)

今回は、変換用の関数を呼ぶだけなので、
同じ引数と戻り値を持つ関数を用意するだけでいい。

では、統一するインタフェースとして、
Encode::from_to を使うことにしよう。
この関数は、変換するデータ、
変換前の文字コード、変換後の文字コードの三つを取り、
戻り値として変換後のバイト数を返す。
失敗すると、undef を返す。

モジュールによる分岐

さて、モジュールのフォールバックは実装できた。
では、肝心な変換部分をどのように呼び出すか。

まず考えられるのが、読み込まれたモジュールを調べ、
それにより分岐する方法だ。

use は内部で require を呼び出している。
require で読み込まれたファイルは、
パッケージ変数 %INC に格納されている。

なので、Encode モジュールが読み込まれているかどうかは、
exists $INC{'Encode.pm'} が真を返すかどうかで分かる。
これを使えば、WRITE メソッド内で分岐させることができる。

モジュールのフォールバック

昨日は、Encode モジュールがあることが前提だった。

そのため、Encpde がない環境で走らせると、
Can't locate Encode.pm in @INC
というエラーになってしまう。

だからといって、最も簡単に導入できる、
jcode.pl を使うと、Unicode の対応ができない。
Encode がある環境では Encode を使いたい、
ない場合は Jcode、それもなければ jcode.pl が理想だ。
つまり、「フォールバック」を行いたい。

ファイルハンドルへの組み込み

文字コード変換をファイルハンドルに組み込んでみよう。

ファイルハンドルクラスには、
変換を行いながら出力を行うことになるので、
最低限 3 つの引数が必要だ。

・実際の出力先ファイルハンドル
・入力の文字コード
・出力の文字コード

引数は、連想配列(ハッシュ)を使って渡すことにしよう。
プログラムの見た目がすっきりするからだ。
使い手が以下のように呼び出せるように作ってみよう。

文字コードの変換

では、文字コードの変換をしてみよう。

まずは、jcode.pl から。
これはモジュールではないため、
懐かしい require 文で取り込む。

require 'jcode.pl';

文字コードを調べるには、getcode を使う。

# 'jis' / 'sjis' / 'euc' / 'binary' / undef が返る。
my $encoding = jcode::getcode(\$data)

文字コード関係のモジュール

ハンドルを乗っ取る方法はわかった。
では、文字コードの変換を考えてみよう。
(文字集合の符号化方式の変換)を考えてみよう。

日本語の文字コードには、ポピュラーなものに、
SHIFT JIS, JIS, EUC の三種類がある。
それぞれ、Windows, 電子メール、UNIX で使用されている。

それらは、利用している文字集合こそ殆ど同じなのだが、
符号化方式(エンコーディング)が異なるため、
プログラムで取り扱うには非常に面倒である。

tie の実験

今日は実験をしてみよう。

ファイルハンドルの tie には、
Tie::Handle という既定の実装が存在する。

この実装は、PRINT, PRINTF, GETC の呼び出しを、
WRITE と READ 用に変換して代わりに呼び出してくれるのだ。
つまり、全てのメソッドを準備する必要がなくなるので、
独自のクラスを作るためには、これを継承すると楽だ。

# 独自クラス。
package NaggingHandle;

ファイルハンドルの tie

Perl 5.8 系の IO レイヤは、
ファイルハンドルの奥底で秘密裏に処理を行う。
5.6 系で同様のことをするためには、
ファイルハンドルに細工をするのが最も速い。
tie 関数を使えばそのようなことが実現できる。

tie の仕組みを使うには、
事前にファイルハンドルとしての動作を模倣する、
パッケージ(クラス)を用意する必要がある。

tie 関数に、ファイルハンドルとパッケージ名を渡せば、
内部でクラスのインスタンスが作成され、
ファイルハンドルに関連付けられる。

< 1 2 3 4 5 6 7 8... >
このページのトップへ戻る
© 2008 Project Loafer/Project Fireball and all blog writers. Powered by Nucleus CMS