CREATE TYPE 文を使用してオブジェクト型仕様を作成し、CREATE TYPE BODY 文を使用してオブジェクト型本体を作成することができます。 本ページでは、CREATE TYPE および CREATE TYPE BODY 文を説明する例を示します。

次の例では、属性は含むがメソッドは含まない addr_object_type オブジェクト型を作成します。

CREATE OR REPLACE TYPE addr_object_type AS OBJECT (
    street          VARCHAR2(30),
    city            VARCHAR2(20),
    state           CHAR(2),
    zip             NUMBER(5)
);

このオブジェクト型にはメソッドがないため、オブジェクト型本体は必要ありません。 この例では、関連するオブジェクトを単一の属性として扱うことができる複合型を作成します。

メンバーメソッド

メンバーメソッドは、オブジェクト型内で定義される関数、またはプロシージャであり、その型のインスタンスを使用してのみ呼び出すことができます。 メンバーメソッドは、操作しているオブジェクトインスタンスの属性にアクセスし、属性を変更することができます。

次の例では、emp_obj_type オブジェクト型を作成します。

CREATE OR REPLACE TYPE emp_obj_type AS OBJECT (
    empno           NUMBER(4),
    ename           VARCHAR2(20),
    addr            ADDR_OBJ_TYPE,
    MEMBER PROCEDURE display_emp(SELF IN OUT emp_obj_type)
);

emp_obj_type オブジェクト型には、display_emp という名前のメンバーメソッドが含まれています。 display_emp は SELF パラメーターを使用します。このパラメーターは、メソッドが呼び出されるオブジェクトインスタンスを渡します。

SELF パラメーターのデータ型は、定義されているオブジェクト型のデータ型と同じです。 SELF パラメーターは常に、メソッドを呼び出しているインスタンスを参照します。 SELF パラメーターは、パラメーターリストで明示的に宣言されているかどうかに関係なく、メンバープロシージャまたは関数の最初のパラメーターです。

次の例では、emp_obj_type のオブジェクト型本体を定義しています。

CREATE OR REPLACE TYPE BODY emp_obj_type AS
    MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_type)
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Employee No   : ' || empno);
        DBMS_OUTPUT.PUT_LINE('Name          : ' || ename);
        DBMS_OUTPUT.PUT_LINE('Street        : ' || addr.street);
        DBMS_OUTPUT.PUT_LINE('City/State/Zip: ' || addr.city || ', ' ||
            addr.state || ' ' || LPAD(addr.zip,5,'0'));
    END;
END;

オブジェクト型本体で SELF パラメーターを使用することもできます。 CREATE TYPE BODY 文で SELF パラメーターがどのように使用されるかを示すために、前述のオブジェクト型の本体を次のように書き換えます。

CREATE OR REPLACE TYPE BODY emp_obj_type AS
    MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_type)
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Employee No   : ' || SELF.empno);
        DBMS_OUTPUT.PUT_LINE('Name          : ' || SELF.ename);
        DBMS_OUTPUT.PUT_LINE('Street        : ' || SELF.addr.street);
        DBMS_OUTPUT.PUT_LINE('City/State/Zip: ' || SELF.addr.city || ', ' ||
            SELF.addr.state || ' ' || LPAD(SELF.addr.zip,5,'0'));
    END;
END;

emp_obj_type 本体の両方のバージョンは同等です。

静的メソッド

メンバーメソッドと同様に、静的メソッドはオブジェクト型に属します。 ただし、静的メソッドは、オブジェクト型のインスタンスではなく、オブジェクト型の名前を使用して呼び出されます。 たとえば、get_count という名前の静的関数を呼び出し、emp_obj_type オブジェクト型内で定義するには、次のように記述します。

emp_obj_type.get_count();

静的メソッドはオブジェクトインスタンスの属性にアクセスできず、属性を変更することはできません。 通常、オブジェクト型のインスタンスでは機能しません。

次のオブジェクト型の仕様には、静的関数 get_dname とメンバープロシージャ display_dept が含まれています。

CREATE OR REPLACE TYPE dept_obj_type AS OBJECT (
    deptno          NUMBER(2),
    STATIC FUNCTION get_dname(p_deptno IN NUMBER) RETURN VARCHAR2,
    MEMBER PROCEDURE display_dept
);

dept_obj_type のオブジェクト型本体は、get_dname という名前の静的関数と、display_dept という名前のメンバープロシージャを定義します。

CREATE OR REPLACE TYPE BODY dept_obj_type AS
    STATIC FUNCTION get_dname(p_deptno IN NUMBER) RETURN VARCHAR2
    IS
        v_dname     VARCHAR2(14);
    BEGIN
        CASE p_deptno
            WHEN 10 THEN v_dname := 'ACCOUNTING';
            WHEN 20 THEN v_dname := 'RESEARCH';
            WHEN 30 THEN v_dname := 'SALES';
            WHEN 40 THEN v_dname := 'OPERATIONS';
            ELSE v_dname := 'UNKNOWN';
        END CASE;
        RETURN v_dname;
    END;
    MEMBER PROCEDURE display_dept
    IS
    BEGIN
        DBMS_OUTPUT.PUT_LINE('Dept No    : ' || SELF.deptno);
        DBMS_OUTPUT.PUT_LINE('Dept Name  : ' ||
            dept_obj_type.get_dname(SELF.deptno));
    END;
END;

静的関数 get_dname 内では、SELF への参照は許可されていません。 静的関数はオブジェクトインスタンスとは独立して呼び出されるため、オブジェクト属性への暗黙的なアクセスはありません。

メンバープロシージャ display_dept は、SELF パラメーターで渡されたオブジェクトインスタンスの deptno 属性にアクセスすることができます。 display_dept パラメーターリストで SELF パラメーターを明示的に宣言する必要はありません。

display_dept プロシージャの最後の DBMS_OUTPUT.PUT_LINE 文には、オブジェクト型名 dept_obj_type で修飾された静的関数 get_dname の呼び出しが含まれています。

コンストラクターメソッド

コンストラクターメソッドは、通常はオブジェクトのメンバーに値を割り当てることによって、オブジェクト型のインスタンスを作成する関数です。 オブジェクト型では、さまざまなタスクを実行するためにいくつかのコンストラクターを定義します。 コンストラクターメソッドは、SELF パラメーターで呼び出されるメンバー関数であり、その名前はオブジェクト型の名前と一致します。

たとえば、address という名前のオブジェクト型を定義すると、各コンストラクターは address という名前になります。 同じ名前でパラメーター型が異なる 1 つ以上のさまざまなコンストラクター関数を作成することにより、コンストラクターをオーバーロードします。

SPL コンパイラーは、オブジェクト型ごとにデフォルトのコンストラクターを提供します。 デフォルトのコンストラクターはメンバー関数です。 その名前はオブジェクト型の名前と一致し、そのパラメーターリストはオブジェクト型のメンバーと順に一致します。 次の例では、address という名前のオブジェクト型を作成します。

CREATE TYPE address AS OBJECT
(
  street_address VARCHAR2(40),
  postal_code    VARCHAR2(10),
  city           VARCHAR2(40),
  state          VARCHAR2(2)
)

SPL コンパイラは、以下のシグニチャーを持つデフォルトのコンストラクターを提供します。

CONSTRUCTOR FUNCTION address
(
  street_address VARCHAR2(40),
  postal_code    VARCHAR2(10),
  city           VARCHAR2(40),
  state          VARCHAR2(2)
)

デフォルトのコンストラクターの本体は、各メンバーを NULL に設定します。

カスタムコンストラクターを作成したい場合は、 CREATE TYPE 文でキーワードコンストラクターを使用してコンストラクターを宣言し、それを CREATE TYPE BODY 文で定義します。 たとえば、street_address と postal_code を指定して都市と州を計算するアドレスオブジェクト型のカスタムコンストラクターを作成する場合は、次のように記述します。

CREATE TYPE address AS OBJECT
(
  street_address VARCHAR2(40),
  postal_code    VARCHAR2(10),
  city           VARCHAR2(40),
  state          VARCHAR2(2),

  CONSTRUCTOR FUNCTION address
   (
     street_address VARCHAR2,
     postal_code VARCHAR2
    ) RETURN self AS RESULT
)
 CREATE TYPE BODY address AS
  CONSTRUCTOR FUNCTION address
   (
     street_address VARCHAR2,
     postal_code VARCHAR2
    ) RETURN self AS RESULT
  IS
    BEGIN
      self.street_address := street_address;
      self.postal_code := postal_code;
      self.city := postal_code_to_city(postal_code);
      self.state := postal_code_to_state(postal_code);
      RETURN;
    END;
END;

オブジェクト型のインスタンスを作成する場合は、そのオブジェクト型のコンストラクターメソッドの 1 つを呼び出します。 例:

DECLARE
  cust_addr address := address('100 Main Street', 02203');
BEGIN
  DBMS_OUTPUT.PUT_LINE(cust_addr.city);  -- displays Boston
  DBMS_OUTPUT.PUT_LINE(cust_addr.state); -- displays MA
END;

カスタムコンストラクターは通常、メンバーの値が不完全な場合にメンバー値を計算するために使用されます。 上記の例では、郵便番号が提供されたときに市と州の値を計算します。

カスタムコンストラクターは、オブジェクトの状態を制限するビジネスルールを適用するためにも使用されます。 たとえば、支払いを表すオブジェクト型を定義する場合には、カスタムコンストラクターを使用して、オブジェクト型支払いのオブジェクトが、NULL、負、またはゼロの金額で作成されないようにすることができます。 デフォルトのコンストラクターは、payment.amount を NULL に設定します。 したがって、NULL 値を禁止するには、シグニチャーがデフォルトのコンストラクターと一致するカスタムコンストラクターを作成する必要があります。