2.2 オブジェクト・メソッド

オブジェクト・メソッドは、その型のオブジェクトが実行する動作を実装します。

内容は次のとおりです。

2.2.1 オブジェクト・メソッドについて

オブジェクト・メソッドとは、定義された型のオブジェクトに実行させる動作を実装する目的で、オブジェクト型定義に宣言できるファンクションまたはプロシージャのことで、サブプログラムとも呼ばれます。アプリケーションは、サブプログラムをコールし、動作を起動します。

サブプログラムは、PL/SQLまたは他のほとんどすべてのプログラミング言語で書くことができます。PL/SQLまたはJavaで書かれたメソッドは、データベースに格納されます。Cのような他の言語で書かれたメソッドは、外部に格納されます。

注意:

SQLでは、引数を持たないサブプログラム・コールについても、すべてカッコを付ける必要があります。これはPL/SQLには適用されません。

関連項目:

PL/SQLでのメソッド起動の詳細は、「オブジェクトのコンストラクタとメソッドに対するコール」を参照してください。

2.2.2 メンバー・メソッド

メンバー・メソッドにより、アプリケーションはオブジェクト・インスタンスのデータにアクセスできます。

オブジェクト型のオブジェクトに実行させるそれぞれの操作について、メンバー・メソッドをオブジェクト型に定義します。比較メソッドでないメンバー・メソッドは、MEMBER FUNCTIONまたはMEMBER PROCEDUREとして定義します。比較メソッドでは、「オブジェクトを比較するためのメンバー・メソッド」で説明するように、MAP MEMBER FUNCTIONまたはORDER MEMBER FUNCTIONを使用します。

たとえば、メンバー・メソッドでは、発注書の明細項目の合計コストを計算するファンクションget_sum()を宣言できます。次のコード行は、発注書poのファンクションをコールし、金額をsum_line_itemsの中に入れて戻します。

sum_line_items:= po.get_sum();abo

ドット表記により、現在のオブジェクトと、そのオブジェクトがコールするメソッドを指定します。パラメータがない場合でも、カッコは必要です。

内容は次のとおりです。

2.2.2.1 メンバー・メソッドでのSELFパラメータの宣言

メンバー・メソッドは、現在メソッドを起動しているオブジェクト・インスタンスを示すSELFと呼ばれる組込みパラメータを持ちます。

SELFは明示的に宣言できますが、必ずしもそうする必要はありません。SELF修飾子を使用せずに暗黙的にSELFの属性とメソッドを参照するメンバー・メソッドを記述するほうが簡単です。例2-8のコードおよびコメントは、属性hgtlenおよびwthを修飾せずに、暗黙的なSELFパラメータを使用するメソッド起動を示しています。

例2-8 メンバー・メソッドの作成

-- Ex. 2-8 Creating a Member Method
CREATE OR REPLACE TYPE solid_typ AS OBJECT (
  len    INTEGER,
  wth    INTEGER,
  hgt    INTEGER,
  MEMBER FUNCTION surface RETURN INTEGER,
  MEMBER FUNCTION volume RETURN INTEGER,
  MEMBER PROCEDURE display (SELF IN OUT NOCOPY solid_typ) );
/

CREATE OR REPLACE TYPE BODY solid_typ AS
  MEMBER FUNCTION volume RETURN INTEGER IS
  BEGIN
    RETURN len * wth * hgt;
 -- RETURN SELF.len * SELF.wth * SELF.hgt; -- equivalent to previous line 
  END;
  MEMBER FUNCTION surface RETURN INTEGER IS
  BEGIN -- not necessary to include SELF in following line
    RETURN 2 * (len * wth + len * hgt + wth * hgt);
  END;
  MEMBER PROCEDURE display (SELF IN OUT NOCOPY solid_typ) IS
  BEGIN
    DBMS_OUTPUT.PUT_LINE('Length: ' || len || ' - '  || 'Width: ' || wth 
                          || ' - '  || 'Height: ' || hgt);
    DBMS_OUTPUT.PUT_LINE('Volume: ' || volume || ' - ' || 'Surface area: ' 
                          || surface);
  END;
END;
/

CREATE TABLE solids of solid_typ;
INSERT INTO solids VALUES(10, 10, 10);
INSERT INTO solids VALUES(3, 4, 5);
SELECT * FROM solids;
SELECT s.volume(), s.surface() FROM solids s WHERE s.len = 10;
DECLARE
  solid solid_typ;
BEGIN -- PL/SQL block for selecting a solid and displaying details
  SELECT VALUE(s) INTO solid FROM solids s WHERE s.len = 10;
  solid.display();
END;
/

SELFは、常にメソッドに最初に渡されるパラメータです。

  • メンバー・ファンクションにSELFが宣言されていない場合、そのパラメータ・モードはデフォルトでINに設定されます。

  • メンバー・プロシージャにSELFが宣言されていない場合、そのパラメータ・モードはデフォルトでIN OUTに設定されます。デフォルトの動作には、NOCOPYコンパイラ・ヒントは含まれません。

2.2.2.2 オブジェクトを比較するためのメンバー・メソッド

オブジェクト型の変数を比較し、順序付けをするには、これらの変数を比較する基準を指定する必要があります。

CHARまたはREALのようなスカラー・データ型の値には、事前定義された順序が存在するため、これらの値は比較できます。ただし、各種のデータ型の属性を多数持つ可能性のあるperson_typのようなオブジェクト型には、事前定義された比較軸は存在しません。オブジェクトを比較する場合、マップ・メソッドかオーダー・メソッドのいずれかを定義できますが、両方を定義することはできません。

マップ・メソッドはオブジェクトの戻り値をスカラー値にマップする他、スカラー軸上の位置に従った複数の値の順序付けが行えます。オーダー・メソッドは特定の2つのオブジェクトの値を直接比較します。

2.2.2.2.1 マップ・メソッドについて

マップ・メソッドは、比較およびソートに使用できる値を戻します。

戻り値は、Oracleの組込みデータ型(LOBおよびBFILEを除く)か、CHARACTERREALなどのANSI SQL型になります。『Oracle Database SQL言語クイック・リファレンス』の該当する項を参照してください。

一般に、マップ・メソッドは、オブジェクトの属性に対して計算を実行して戻り値を生成します。

マップ・メソッドは自動的にコールされ、obj_1 > obj_2のような比較や、行によるソートを必要とするDISTINCTGROUP BYUNIONおよびORDER BY句によって示される比較を評価します。

obj_1およびobj_2がマップ・メソッドmap()を使用して比較できる2つのオブジェクト変数であるとすると、次の比較は、

obj_1 > obj_2

次の比較と同等になります。

obj_1.map() > obj_2.map()

他のリレーショナル演算子についても、比較は同様です。

「マップ・メソッドの作成」では、四角形オブジェクトを面積で比較する際の基準を規定するマップ・メソッドarea()を定義しています。

2.2.2.2.2 マップ・メソッドの作成

CREATE TYPE文を使用してマップを作成します。

例2-9 マップ・メソッドの作成

CREATE OR REPLACE TYPE rectangle_typ AS OBJECT ( 
  len NUMBER,
  wid NUMBER,
  MAP MEMBER FUNCTION area RETURN NUMBER);
/

CREATE OR REPLACE TYPE BODY rectangle_typ AS 
  MAP MEMBER FUNCTION area RETURN NUMBER IS
  BEGIN
     RETURN len * wid;
  END area;
END;
/
2.2.2.2.3 マップ・メソッドの起動

マップ・メソッドは、他のメンバー・メソッドと同じ方法で起動します。

例2-10 マップ・メソッドの起動

DECLARE
  po rectangle_typ;
 
BEGIN
  po :=NEW rectangle_typ(10,5);
 
DBMS_OUTPUT.PUT_LINE('AREA:' || po.area()); -- prints AREA:50
  END;
/

サブタイプの場合は、そのルート・スーパータイプでマップ・メソッドを宣言している場合にかぎり、マップ・メソッドを宣言できます。

オブジェクト型が含まれているコレクションを比較する際のマップ・メソッドの使用方法は、「等価および非等価条件の比較」を参照してください。

2.2.2.2.4 オーダー・メソッド

オーダー・メソッドは、オブジェクトを1対1で直接比較します。

マップ・メソッドとは異なり、オーダー・メソッドは多数のオブジェクトの順序を判別できません。オーダー・メソッドは、使用されている基準に基づいて、現在のオブジェクトが比較対象のオブジェクトより小さいか、等しいかまたは大きいかを知らせるのみです。

オーダー・メソッドはオブジェクト(SELF)のファンクションの1つで、宣言されたパラメータ(同じ型のオブジェクト)を1つ持ちます。このメソッドは、負の数、0 (ゼロ)または正の数のいずれかを戻す必要があります。この値は、オブジェクト(宣言されていない暗黙的なSELFパラメータ)が、宣言されているパラメータ・オブジェクトより小さいか、等しいかまたは大きいかを示します。

マップ・メソッドと同様、オーダー・メソッドを定義した場合、その型を持つ2つのオブジェクトを比較する必要があれば、自動的にコールされます。

オーダー・メソッドは、比較セマンティクスが複雑すぎてマップ・メソッドが使用できない場合に役立ちます。

例2-11に、建物番号で場所を比較するオーダー・メソッドを示します。

例2-11 オーダー・メソッドの作成および起動

DROP TYPE location_typ FORCE;
-- above necessary if you have previously created object
CREATE OR REPLACE TYPE location_typ AS OBJECT (
  building_no  NUMBER,
  city         VARCHAR2(40),
  ORDER MEMBER FUNCTION match (l location_typ) RETURN INTEGER );/
CREATE OR REPLACE TYPE BODY location_typ AS 
  ORDER MEMBER FUNCTION match (l location_typ) RETURN INTEGER IS 
  BEGIN 
    IF building_no < l.building_no THEN
      RETURN -1;               -- any negative number will do
    ELSIF building_no > l.building_no THEN 
      RETURN 1;                -- any positive number will do
    ELSE 
      RETURN 0;
    END IF;
  END;
END;/

-- invoking match method
DECLARE
loc location_typ;
secloc location_typ;
a number;
 
BEGIN
 loc :=NEW location_typ(300, 'San Francisco');
 secloc :=NEW location_typ(200, 'Redwood Shores');
 a := loc.match(secloc);
 
DBMS_OUTPUT.PUT_LINE('order (1 is greater, -1 is lesser):' ||a); -- prints order:1 
 END;
/

導出元が別の型ではない型のみ、オーダー・メソッドが宣言できます。サブタイプはオーダー・メソッドを宣言できません。

2.2.2.2.5 比較メソッドのガイドライン

宣言できるのは、マップ・メソッドかオーダー・メソッドのいずれか一方で、両方を宣言することはできません。

マップ・タイプ・メソッドでもオーダー・タイプ・メソッドでも、SQL文およびPL/SQLプロシージャ文を使用してオブジェクトを比較できます。ただし、どちらのメソッドも宣言しない場合でも、SQL文の中にあるオブジェクトについてのみ、等価比較または不等価比較が行えます。同じ型の2つのオブジェクトは、対応する属性の値が一致する場合のみ、等価とみなされます。

多数のオブジェクトをソートまたはマージする際はマップ・メソッドを使用し、その場合、すべてのオブジェクトがスカラー値にマップされた後、スカラー値がソートされます。オーダー・メソッドは繰り返してコールする必要があるため、効率的ではありません(一度に比較できるのは2つのオブジェクトのみです)。

2.2.2.2.6 型の階層内の比較メソッド

型階層で、ルート型(スーパータイプ)がマップ・メソッドとオーダー・メソッドのいずれも指定していない場合、どちらのメソッドもサブタイプになることはできません。

  • 型の階層内のマップ・メソッド

    ルート型がマップ・メソッドを指定している場合、そのサブタイプはいずれもマップ・メソッドをオーバーライドできます。ルート型がマップ・メソッドを定義していない場合、サブタイプはマップ・メソッドを定義できません。

  • 型の階層内のオーダー・メソッド

    オーダー・メソッドを定義できるのは、ルート型のみです。ルート型がオーダー・メソッドを定義していない場合、そのサブタイプはオーダー・メソッドを追加できません。

2.2.3 静的メソッドの宣言および起動

静的メソッドはオブジェクトのインスタンスではなく、オブジェクト型に対して起動されます。静的メソッドは、型に対してグローバルに適用され、特定のオブジェクトのインスタンスのデータを参照する必要のない操作に使用します。静的メソッドは、SELFパラメータを持ちません。

静的メソッドは、STATIC FUNCTIONまたはSTATIC PROCEDUREを使用して宣言します。

静的メソッドは、たとえば次のように、ドット表記法によりメソッド・コールにオブジェクト型の名前を付けて修飾して起動します。

type_name.method()

関連項目:

設計上の考慮事項の詳細は、静的メソッドを参照してください。

2.2.4 コンストラクタ・メソッド

コンストラクタ・メソッドは、ユーザー定義型の新しいインスタンスを戻し、その属性の値を設定するファンクションです。

コンストラクタ・メソッドは、システム定義かユーザー定義のいずれかです。

コンストラクタを起動するには、キーワードNEWを使用できますが、必ずしもそうする必要はありません。

2.2.4.1 システム定義コンストラクタ

デフォルトでは、属性を持つすべてのオブジェクト型についてコンストラクタ・ファンクションが暗黙的に定義されます。

システム定義コンストラクタは、属性値コンストラクタと呼ばれることもあります。例2-1で定義されているperson_typオブジェクト型の場合、次の起動に示すように、コンストラクタ・メソッドの名前はオブジェクト型の名前になります。

person_typ (1, 'John Smith', '1-650-555-0135'),

2.2.4.2 ユーザー定義コンストラクタの定義

ユーザー独自のコンストラクタ・ファンクションを定義して、ユーザー定義型を作成および初期化することができます。

デフォルトのシステム定義コンストラクタ(属性値コンストラクタ)はすでに存在するため便利ですが、ユーザー定義コンストラクタには型進化に関する重要な利点があります。

関連項目:

2.2.4.3 コンストラクタ・メソッドのリテラル起動

コンストラクタ・メソッドのリテラル起動とは、(バインド変数とは対照的に)引数がリテラルか、またはさらに続くコンストラクタ・メソッドのリテラル起動のいずれかをとるコンストラクタ・メソッドのコールのことです。次に例を示します。

CREATE TABLE people_tab OF person_typ;

INSERT INTO people_tab VALUES (
       person_typ(101, 'John Smith', '1-650-555-0135') );

2.2.5 外部実装メソッド

PL/SQLを使用して、他の言語で作成された外部のサブプログラムを起動できます。

外部実装メソッドを使用すると、そのような言語の長所や機能を活用できます。