您可以使用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_typ物件類型:
CREATE OR REPLACE TYPE emp_obj_typ AS OBJECT (
empno NUMBER(4),
ename VARCHAR2(20),
addr addr_object_type,
MEMBER PROCEDURE display_emp(SELF IN OUT emp_obj_typ)
);物件類型emp_obj_typ包含一個名為display_emp的成員方法。display_emp使用SELF參數,後者傳遞調用該方法的對象執行個體。
SELF參數的資料類型是所定義的物件類型的資料類型。SELF始終引用調用方法的執行個體。SELF參數是成員預存程序或函數中的第一個參數,無論它是否在參數列表中明確聲明。
以下程式碼片段為emp_obj_typ定義物件類型主體:
CREATE OR REPLACE TYPE BODY emp_obj_typ AS
MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_typ)
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_typ AS
MEMBER PROCEDURE display_emp (SELF IN OUT emp_obj_typ)
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_typ主體完全相同。
靜態方法
與成員方法一樣,靜態方法也屬於某一類型。但是靜態方法不是由類型的執行個體進行調用,而是通過使用類型的名稱進行調用。例如,要調用 emp_obj_type 類型中定義的名為 get_count 的靜態函數,您將編寫以下語句:
emp_obj_type.get_count();靜態方法無權訪問對象執行個體的屬性,也不能更改這些屬性,並且通常不使用類型的執行個體。
以下物件類型規格包含靜態函數get_dname和成員預存程序display_dept:
CREATE OR REPLACE TYPE dept_obj_typ AS OBJECT (
deptno NUMBER(2),
STATIC FUNCTION get_dname(p_deptno IN NUMBER) RETURN VARCHAR2,
MEMBER PROCEDURE display_dept
);dept_obj_typ的物件類型主體定義一個名為get_dname的靜態函數和一個名為display_dept的成員預存程序:
CREATE OR REPLACE TYPE BODY dept_obj_typ 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_typ.get_dname(SELF.deptno));
END;
END;在靜態函數get_dname中,不能有對SELF的引用。由於靜態函數的調用獨立於任何對象執行個體,因此沒有對任何對象屬性的隱式訪問權。
成員預存程序display_dept可以訪問SELF參數中傳遞的對象執行個體的deptno屬性。不必在display_dept參數列表中明確聲明SELF參數。
display_dept預存程序中的最後一個DBMS_OUTPUT.PUT_LINE語句包含對靜態函數get_dname(由其物件類型名稱dept_obj_typ限定)的調用。
建構函式方法
建構函式方法是一個函數,該函數通過為對象的成員分配值來建立物件類型的執行個體。物件類型可以定義多個建構函式來完成不同的任務。建構函式方法是一個成員函數(通過SELF參數進行調用),其名稱與類型的名稱相匹配。
例如,如果定義名為address的類型,則每個建構函式也名為address。通過建立一個或多個同名但參數類型不同的不同建構函式,可以重載建構函式。
SPL編譯器將為每個物件類型提供預設建構函式。預設建構函式是一個成員函數,其名稱與類型的名稱匹配,並且其參數列表與類型成員也匹配(按順序)。例如,給出如下物件類型:
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中聲明該建構函式(使用關鍵字constructor),然後在CREATE TYPE BODY命令中定義該建構函式。例如,您可能希望為address類型建立一個自訂建構函式,它在給出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;要建立物件類型的執行個體,將調用該類型的某一建構函式方法。例如:
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;自訂建構函式通常用於在給定的資訊不完整時導出成員值。上一樣本在給出郵遞區號時計算city和state的值。
自訂建構函式還用於強制執行限制對象狀態的商務規則。例如,如果定義一個物件類型來代表payment,您可以使用自訂建構函式確保不能建立amount為NULL、負數或零的payment類型的對象。預設建構函式將payment.amount設定為NULL,因此您必須建立一個自訂建構函式(其特徵與預設建構函式相匹配)來禁止金額為NULL。