
第 4 回では、PowerScript の文法的な「癖」を学びました。変数のスコープや NULL の挙動に戸惑いつつも、「意外と素直な言語だな」と感じ始めている頃ではないでしょうか。
連載第 5 回となる今回は、PowerBuilder (PB) の設計の骨格となる「オブジェクト指向」と「イベント駆動」について解説します。Web エンジニアが使い慣れた「コンポーネント」や「イベントリスナー」という概念が、PowerBuilder では「継承」という強力な武器を通じてどう表現されるのか。その実態に迫ります。
Web 開発において、画面 (Page) は URL に対応するルートコンポーネントであることが一般的です。しかし、PowerBuilder における Window は、それ自体が一つの独立した「クラス (Class)」として定義されます。
Window の中には、これまでに学んだデータウィンドウやボタン、入力フィールドなどの「コントロール」が配置されます。これらは Web フロントエンドでいうところの「子コンポーネント」に相当しますが、決定的な違いは、Window そのものがプロパティ (状態)、関数 (メソッド)、およびイベントを保持する完全なオブジェクト指向のクラスである点です。
Open(w_detail) のように関数を呼び出し、Window クラスを明示的にインスタンス化して画面に表示します。Web 開発 (JavaScript) では、addEventListener や onClick={…} のように、イベントに対して関数を「アタッチ」します。
一方、PowerBuilder では、オブジェクトごとにあらかじめ定義された「イベント」という名のスロットに直接コード (スクリプト) を記述します。
| イベント名 (PB) | Web での相当概念 | 実行タイミング |
|---|---|---|
| Open | useEffect(() => …, []) / onLoad | Window がメモリにロードされ、表示される直前 |
| Close | onUnmount | Window が閉じられる直前 |
| Clicked | onClick | コントロールがクリックされたとき |
| ItemChanged | onChange + Validation | データウィンドウの入力値が変更され、確定したとき |
PowerBuilder のイベント駆動における面白い特徴が、「イベントの戻り値によって、その後に続くフレームワーク側の挙動をコントロールする」という仕組みです。
例えば、DataWindow (グリッドやフォームに相当するコンポーネント) の ItemChanged イベント (Web でいう onChange) を例に挙げてみましょう。
ItemChanged イベント (データウィンドウへの入力時)
// 未入力の場合 IF String(data) = "" THEN Return 1 // 入力を拒否し、フォーカスを移動させない END IF
event.preventDefault() との違いWeb 開発では、イベントの既定動作を止めたいときに event.preventDefault() というメソッドを呼び出します。PowerBuilder ではこれを戻り値に特定の数値を返すことで実現します。
Web のキャンセルが「やるか・やらないか」の 2 択 (Boolean) に近いのに対し、PowerBuilder のイベントの戻り値は「フレームワーク (システム) に対する命令の分岐」になっています。
Return 0 (デフォルト)
Return 1
Return 2
現代のフロントエンド開発 (React や Vue など) では、「継承より合成 (Composition over Inheritance)」がベストプラクティスとされています。コンポーネントを細かく分割し、Props や Slot で組み合わせる手法です。しかし、PowerBuilder の世界では「継承 (Inheritance)」こそが最強のアーキテクチャです。
Web 開発で「Props のバケツリレー」や「同じコンポーネントを何重にもラップする構造」にウンザリした経験はありませんか?PowerBuilder では、既存の Window (画面) や UserObject (コンポーネント) を「先祖」として、その資産をダイレクトに引き継いだ「子孫」を無制限に作ることができます。
たとえば、すべての画面に共通の「閉じるボタン」や「ログ出力機能」を持たせ、これを先祖として入力系画面には「登録」「削除」、一覧系画面には「検索」「参照」など共通の処理と、それに対応するボタンやデータウィンドウなどのコントロールを追加します。さらにそれらを先祖としてカスタマイズして各画面を作成することで、システム全体の UI 統一に加え、開発工数を大幅に削減し保守性を高めることができます。

見た目 (UI) とロジック (イベント・関数) をセットで一発継承
Web では、ロジックを Hooks や Composable に切り出せても、UI (ボタンの配置やレイアウト) まで綺麗に密結合させて継承するのは困難です。PowerBuilder は、先祖の「見た目」も「ボタンを押した時の裏の処理」も、すべて丸ごと子孫が引き継ぎます。
「先祖の処理」を 1 行で呼び出せる (拡張の容易さ)
子孫側で「先祖の動きをちょっとだけ変えたい」という場合、子孫のイベント内で SUPER:: ユーザーイベント名() または Super:: 関数名 () と書くだけで、先祖の共通処理を実行しつつ、子孫独自のロジックを前後にサンドイッチできます。ラッパー関数を何重も定義する必要はありません。
共通処理の修正が必要になったら、先祖を 1 か所直すだけで、数百画面ある子孫すべてに即座に反映されます。この圧倒的な開発スピードと統制力こそが、大規模エンタープライズ開発で PowerBuilder が長年愛され続ける理由です。
「再利用可能な UI パーツやロジック」を作りたい場合、PowerBuilder では UserObject (UO) を使用します。これこそが、Web 開発における Component (コンポーネント) そのものです。
Visual UserObject (UI 用のユーザーオブジェクト) :
ボタンや入力欄、あるいはデータウィンドウを組み合わせたカスタムコントロールです。Web でいう「検索条件フォーム」「共通ナビゲーション」のようなパーツに相当します。作成した UO は、コンポーネントのインポート文を書く必要すらなく、開発画面 (IDE) 上で Window にドラッグ & ドロップするだけで配置できます。
Non-Visual Object (UI を持たないユーザーオブジェクト):
UI (見た目) を一切持たない純粋なクラスです。Web 開発における「Service 層」「カスタム Hooks」「Logic クラス」に相当します。PowerBuilder でも、画面 (Window) に直接ビジネスロジックを書き殴るとすぐにコードがスパゲッティ化します。そのため、ロジックを NVO に切り出し、Window からはインスタンスを生成して呼び出すのが、PowerBuilder 開発におけるベストプラクティスです。
PowerBuilder のオブジェクト指向は、「継承」の仕組みを徹底的に活かすことで、大規模開発における高い生産性と強固な統制力を両立させる設計モデルです。
Web の「自由で柔軟なコンポジション」に慣れた身には、最初は窮屈に感じるかもしれません。しかし、何百画面もの巨大な業務アプリを破綻させずに作り切る際、この厳格なオブジェクト指向のルールがいかに鉄壁のメンテナンス性を生み出すかを実感できるはずです。
「Web エンジニア向け PB 入門」バックナンバー