오브젝트 타입

추상 데이터 타입인 오브젝트 타입에 대해서 설명합니다.

개요

오브젝트 타입(Object Type)은 데이터 타입의 데이터 구성 요소와 서브 프로그램을 캡슐화(Encapsulation) 한 추상 데이터 타입(Abstract Data Type)입니다.

데이터 구성요소는 Attribute라고 부르며, 서브 프로그램은 메소드(Method)라고 부릅니다. 사용자는 추상 데이터 타입을 이용하여 애플리케이션에 관련된 데이터와 서브 프로그램을 한 곳으로 모을 수 있어 애플리케이션 작성이 쉬워지고 가독성이 높아집니다.

tbPSM의 오브젝트 타입이 클래스나 패키지와의 다른점은 다음과 같습니다.

  • 클래스와 다른 점은 상속성과 다형성이 제외된 순수한 추상 데이터 타입이라는 것입니다. (상속성과 다형 성은 추후 추가 예정)

  • 패키지와 다른 점은 타입 실체화입니다.

    • 오브젝트 타입의 변수는 컬렉션 타입 변수처럼 각각 다른 메모리 공간을 사용합니다.

    • 패키지 자체가 세션마다 유일한 데이터 셋를 가지는 반면 오브젝트 타입 자체로는 데이터 셋을 가지지 않으며 오브젝트 타입 실체화를 통해 각각의 인스턴스마다 데이터 셋를 가집니다.

    • 오브젝트 타입의 실체화 방법은 컬렉션 타입과 동일하게 생성자를 호출하는 것이며, 생성자가 삭제되는 것은 변수의 생명 주기와 같습니다.

    • 변수의 Block Scope가 끝났을 경우 오브젝트 인스턴스에 대한 메모리가 해제됩니다. 단, 패키지 멤버 변수인 경우에는 패키지 인스턴스가 무효화 되는 경우에 삭제됩니다.

circle-info

참고

tbPSM의 오브젝트 타입은 tbPSM 내에서 사용되는 기능만 구현되었으므로 SQL이나 테이블을 생성 하는 곳에서는 사용이 불가능합니다. (기능 추가 예정)

다음은 오브젝트 타입을 이용한 Number Stack의 구현 예로 Stack의 데이터 배열과 Top 포인터, 그리고 푸쉬(Push), 팝(Pop), 탑(Top) 동작을 한 곳으로 모은 것을 확인할 수 있습니다.

DROP TYPE number_array FORCE;

-- Stack 내부에서 사용하는 데이터를 위한 최대 크기의 한계가 없는 배열 데이터 타입
CREATE OR REPLACE TYPE number_array AS TABLE OF NUMBER;
/
show err

DROP TYPE type_nstack force;

-- number stack의 추상 데이터 타입
CREATE OR REPLACE TYPE type_nstack AS OBJECT(
    maxlen pls_integer, -- Stack의 최대 크기 
    topptr pls_integer, -- Stack의 TOP 
    array number_array, -- Stack 내부 데이터

    MEMBER PROCEDURE pop (self in out nocopy type_nstack),
    MEMBER FUNCTION top (self in out nocopy type_nstack) return NUMBER, 
    MEMBER PROCEDURE push (self in out nocopy type_nstack, input NUMBER),
    CONSTRUCTOR FUNCTION type_nstack(maxlen pls_integer) RETURN SELF AS RESULT
);
/
show err

CREATE OR REPLACE TYPE BODY type_nstack 
AS
    MEMBER PROCEDURE pop (self in out nocopy type_nstack) 
    AS
    BEGIN
        IF topptr <= 0 THEN
            raise_application_error(-20000, 'stack is empty', true); 
        ELSE
            array(topptr) := NULL; 
            topptr := topptr - 1;
        END IF; 
    END;

    MEMBER FUNCTION top (self in out nocopy type_nstack) return NUMBER 
    AS
    BEGIN
        IF topptr <= 0 THEN 
            return NULL;
        ELSE
            return array(topptr); 
        END IF;
        return NULL; 
    END;

    MEMBER PROCEDURE push (self in out nocopy type_nstack, input NUMBER) 
    AS
    BEGIN
        IF topptr = maxlen THEN
            raise_application_error(-20001, 'stack is full', true); 
        ELSE
            array(self.topptr + 1) := input; 
            topptr := topptr + 1;
        END IF; 
    END;

    CONSTRUCTOR FUNCTION type_nstack(maxlen pls_integer) RETURN SELF AS RESULT 
    AS
    BEGIN
        array := number_array(); 
        array.extend(maxlen); 
        topptr := 0;
        RETURN; 
    END;
END;
/
show err

set serveroutput on
-- 간단한, Stack Push/Pop 동작 테스트 애플리케이션
declare
    s1 type_nstack; 
begin

    s1 := type_nstack(4); -- 최대 크기 4짜리 Stack의 생성
    s1.push(10); -- 10을 Push 
    s1.push(20); -- 20을 Push 
    s1.push(30); -- 30을 Push 
    s1.push(40); -- 40을 Push

    dbms_output.put_line (s1.top);    -- Stack의 Top을 조회
    s1.pop;   -- stack pop

    dbms_output.put_line (s1.top);   -- Stack의 Top을 조회
    dbms_output.put_line (s1.top);   -- Stack의 Top을 조회

    s1.pop;   -- stack pop
    dbms_output.put_line (s1.top);   -- Stack의 Top을 조회

    s1.pop;	-- stack pop 
    s1.pop;	-- stack pop
    s1.pop;	-- stack pop : Stack이 비어 있으므로 에러
end;
/

생성자

생성자는 디폴트 생성자와 사용자 정의 생성자가 있습니다.

디폴트 생성자

사용자 정의 생성자가 없는 경우 디폴트 생성자가 호출되며, 디폴트 생성자의 함수 시그니쳐는 Attribute 의 순서와 동일합니다. 호출자가 argument로 다른 타입을 가지고 생성자를 호출하는 경우 tbPSM implicit type conversion rule을 따릅니다. 만약 오브젝트 변수가 NULL일 경우 생성자 함수 호출 중에 Exception이 발생합니다(오브젝트 인스턴스가 NULL일 경우 Attribute는 항상 NULL입니다).

다음은 디폴트 생성자를 호출하는 예입니다.

사용자 정의 생성자

사용자 정의 생성자가 디폴트 생성자와 시그니쳐가 다르면 함수 오버로딩 규칙에 따라 타입 변환이 가장 적고 정보 손실이 가장 적은 쪽을 우선적으로 선택합니다. 만약 선택하지 못하는 경우 컴파일 에러가 발생합니다. 사용자 정의 생성자를 생성할 때 오브젝트 변수는 기본으로 NULL 값을 가집니다. 사용자 정의 생성자에 대한 자세한 설명은 “메소드”의 “생성자 메소드”를 참고합니다.

다음은 사용자 정의 생성자를 호출하는 예입니다.

Attribute

Attribute는 오브젝트 타입의 구성요소인 데이터들입니다.

  • 원시 데이터 타입(Primitive Data Type)

  • 오브젝트 타입(Object Type)

  • 컬렉션 타입(Collection Type) 중 인덱스 바이 테이블 타입(Index by table Type)을 제외한 배열 타입(Varray Type)

  • 테이블 타입(Table Type)

레코드 타입(Record Type)은 Attribute 타입으로 사용될 수 없습니다. 레코드 타입과 인덱스 바이 테이블 타입은 tbPSM 로컬 타입(tbPSM BLOCK 안에서 선언 가능)이기 때문입니다. 즉, 원시 데이터 타입과 create type DDL 문으로 선언하는 타입은 Attribute 타입으로 사용 가능합니다. Attribute의 이름은 중복을 허용하지 않으 며, 메소드 이름과 중복되면 안됩니다.

다음은 컬렉션 타입과 오브젝트 타입을 혼합 사용한 예입니다.

메소드

메소드는 오브젝트 타입에 필요한 서브 프로그램입니다.

  • 생성자 메소드

  • 정적 메소드

  • ORDER 메소드

  • MAP 메소드

  • 멤버 메소드

정적 메소드, 멤버 메소드는 함수나 프러시저가 가능하고, ORDER 메소드와 MAP 메소드는 함수만 가능합니다. 오프젝트 타입은 ORDER 메소드나 MAP 메소드 둘 중에 하나만 가질 수 있습니다.

생성자 메소드

사용자 정의 생성자를 생성할 때 리턴 문에 리턴 값을 써주지 않더라도 암묵적으로 새 인스턴스를 반환합니다. 사용자 정의 생성자의 첫 번째 파라미터로 SELF라는 이름의 자기 자신의 타입을 가지는 파라미터를 명시 가능하지만 지정하지 않는 것과 동일합니다. 첫 번째 파라미터를 SELF로 지정하지 않더라도 암묵적으로 SELF가 있는 것과 같기 때문입니다(암묵적인 SELF는 IN/OUT NOCOPY 파라미터입니다).

정적 메소드

정적 메소드는 오브젝트 INSTANTIATION을 하지 않고도 호출이 가능한 메소드로 다음과 같은 형태로 호출합니다.

정적 메소드는 타입 이름을 가지고 호출하기 때문에 생성자의 호출과 상관없이 불리는 경우 인스턴스에 대한 접근이 불가능합니다. 즉, 정적 메소드는 인스턴스 데이터 접근과 전혀 상관없는 경우에만 사용되어야 합니다.

다음은 정적 메소드의 사용 예입니다.

ORDER 메소드

ORDER 메소드는 두 개의 오브젝트 인스턴스를 비교하기 위해 사용되는 메소드입니다. 매개변수로 SELF 를 제외하고 유일한 자기 자신의 타입을 가지는 파라미터 하나가 있어야 합니다. 또한 리턴 값은 숫자 타입 (Number, Bin_Integer, Binary_double, Binary_float와 그에 따른 Sub Type)만을 가져야 합니다.

만약 이항 비교 연산자가 표현식에 존재하는 경우 a "비교연산자" b는 다음과 같이 변환되어 오브젝트 인 스턴스의 비교가 가능하도록 합니다. 이러한 기능은 tbPSM 표현식에서만 가능하고 SQL에서는 사용 불가능합니다.

MAP 메소드와 ORDER 메소드의 파라미터와 반환값 비교는 다음과 같습니다.

메소드
파라미터
반환값

MAP

SELF를 제외하고 파라미터 사용이 불가능

Primitive Data Type

ORDER

SELF를 제외하고 자기 자신 타입을 가지는 1개의 IN 파라미터 사용이 가능

숫자 타입

  • Number

  • Bin_Integer

  • Binary_double

  • Binary_float

  • 그에 따른 Sub Type

사용자는 두 개의 파라미터를 비교하여 다음과 같이 메소드를 작성해야 합니다.

  • SELF가 더 큰 경우: 음수를 리턴합니다.

  • 두개가 같은 경우: 0을 리턴합니다.

  • SELF가 작은 경우: 양수를 리턴합니다.

다음은 Stack 타입의 ORDER 메소드 작성을 이용하여 두 개의 Stack을 비교하는 예입니다. (Stack의 element개수가 많은것이 더 값이 크다고 가정)

MAP 메소드

MAP 메소드는 인스턴스에서 primitive 타입의 scalar 값을 리턴하는 메소드입니다. 함수는 SELF 외에 아무런 파라미터가 있어서는 안되며 primitive 타입을 리턴해야 합니다. 만약 이항 연산자가 있는 경우 a < b는 다 음과 같이 변환되어 오브젝트 인스턴스의 비교가 가능하도록 합니다.

다음은 MAP 메소드의 사용 예입니다.

멤버 메소드

멤버 메소드는 다음과 같은 형태로 호출합니다.

멤버 메소드는 첫 번째 파라미터가 암묵적인 SELF 파라미터로 자기 자신의 타입을 가지는 파라미터입니다. 기본 속성은 IN 파라미터이며 사용자가 IN/OUT 형태로 변경이 가능합니다. IN으로 사용하면 Attribute 값을 변경할 수 없고 리턴을 통해 변경이 가능하므로 원소적인 동작을 취할수 있습니다. SELF 파라미터는 인스턴스 데이터에 접근할 수 있도록 해주며 "SELF"."Attribute 이름"으로 사용하거나 "Attribute 이름"으로 직접 사용이 가능합니다.

멤버 메소드는 OVERLOADING이 가능하지만 MAP, ORDER 메소드는 OVERLOADING이 불가능합니다. 멤버 메소드는 LOCAL METHOD(BODY에서만 사용 가능한 메소드)를 정의할 수 습니다. 항상 TYPE OBJECT 에 기술된 메소드가 정확히 BODY에도 존재해야 하며, BODY에 존재하는 메소드는 반드시 TYPE OBJECT 에 기술되야 합니다.

다음은 Number Stack의 사용 예입니다.

오브젝트 관련 정적 뷰

다음은 오브젝트 관련 정적 뷰입니다.

  • ALL_TYPES, DBA_TYPES, USER_TYPES

  • ALL_COLL_TYPES, DBA_COLL_TYPES, USER_COLL_TYPES

  • ALL_TYPE_ATTRS, DBA_TYPE_ATTRS, USER_TYPE_ATTRS

  • ALL_TYPE_METHODS, DBA_TYPE_METHODS, USER_TYPE_METHODS

  • ALL_METHOD_PARAMS, DBA_METHOD_PARAMS, USER_METHOD_PARAMS

  • ALL_METHOD_RESULTS, DBA_METHOD_RESULTS, USER_METHOD_RESULTS

circle-info

참고

해당 뷰에 대한 자세한 내용은 "Tibero 참조 안내서"의 "제3장 Static View"를 참고합니다.

Last updated