2009-10-16 2 views
2

오라클의 PL/SQL (10g 사용)에 대해 약간 새로운 점이 있습니다. 개인용 도우미 메소드의 경우처럼 객체 유형에 전용 메소드를 만드는 방법이 있는지 궁금합니다. 다른 언어 (Java, C++, C# 등). I 알 수 있습니다 패키지에서 개인 메서드를 만들 수 있지만 개체 형식이 작업을 수행하는 방법을 찾을 수 없습니다. 당신은 PL/SQL 객체의 private 메소드를 가질 수 없습니다PL/SQL 전용 객체 메소드

Error: PLS-00539: subprogram 'FOO' is declared in an object type body 
and must be defined in the object type specification.

답변

1

, 당신이 다형성과 상속하지만 캡슐화를 가질 수있다 : 나는 컴파일러 말해 오류가 계속.

캡슐화 (개인 메소드)를 원하면 pl/sql 패키지를 사용할 수 있습니다.

한 번에 세 가지를 모두 수행 할 수 없습니다.

+0

좋아, 그게 어려운 일이 될거야. 여러 생성자가있는 객체 유형이 있지만 모두 동일한 인수를 사용하지는 않지만 모두 공통 코드가 4-5 줄입니다. PL/SQL이 생성자 연결을 허용하지 않는다는 것을 이미 알았 기 때문에 공용 설정 코드를 개인 메소드에 넣을 수 있다고 생각했습니다. 이런 종류의 문제에 대한 좋은 PL/SQL 솔루션은 무엇입니까? – PrivateMethodMan

+0

잘 모르겠습니다. 어쩌면 객체를 반환하는 오버로드 된 함수를 사용하여 패키지를 만들 수 있습니까? Oracle을 지금 사용할 수 없어서 시도 할 수 없습니다. 대체 공장으로 간주하십시오. – tuinstoel

+0

사실 ... 이것은 또 다른 좋은 점을 제기합니다. 객체 유형의 여러 메소드에서 공통 코드를 찾으면 어떻게 리팩토링합니까? 나는 그것을 private 메소드로 감당할 수 없다. 존재하는 클래스 밖에서는 아무 것도 호출 할 수없는 public 메소드에 그것을 고려하는 방법이 있는가? 아니면 "내부 집 유지 방법 - 손을 놓아 라!"라고 문서화해야합니다. 아무도 원래 수업 시간에 그것을 부르지 않기를 바랍니다. – PrivateMethodMan

2

이 좋아, 여기에 내가 아주 간단히 테스트 잠재적 인 솔루션, 그리고 지금까지 작동하는 것 같다 :

후 최종 NOT과 INSTANTIABLE NOT과 같이 표시됩니다 부모 개체 유형을 만들기에있는 모든 개인 코드를 삽입 그곳에. private 메소드는 진정으로 private는 아니지만 final이 아니고 인스턴스화 할 수없는 유형으로 호출하면 호출되지 않습니다. 인스턴스화 가능한 부속 유형에서, SELF를 통해 4 퍼 유형의 "개인"메소드를 참조하십시오. 예 :


create or replace type PrivateFoo under SuperFoo 
(

    member procedure setUpCommonFoo 
) NOT INSTANTIABLE NOT FINAL; 

create or replace type body PrivateFoo is 
    -- Member procedures and functions 
    member procedure setUpCommonFoo is 
     begin 
      SELF.someAttrib:='Some Common Default Value'; 
     end; 
end; 

create or replace type Foo under PrivateFoo 
(
    CONSTRUCTOR FUNCTION Foo RETURN SELF AS RESULT, 
    CONSTRUCTOR FUNCTION Foo(fkey FooKey) RETURN SELF AS RESULT -- assume fkey is defined in SuperFoo, and FooKey type is defined somewhere else ;) 
) 

create or replace type body Foo is 
    --no-arg Constructor For basic Foo set up. 
    CONSTRUCTOR FUNCTION PartyConvertor RETURN SELF AS RESULT AS 
    BEGIN 
     self.setUpCommonFoo; 
     RETURN; 
    END; 
     --alt constructor for other situations... 
    CONSTRUCTOR FUNCTION PartyConvertor(fkey FooKey) RETURN SELF AS RESULT AS 
    BEGIN 
     self.setUpCommonFoo; 
       SELF.rarelyUsedAttrib:='Special Value!'; --just assume that someAttrib and rarelyUsedAttrib actually exist ;) 
     self.fkey := fkey; 
     RETURN; 
    END; 
     --Other Members go here... 
end; 

지금 나는이 패턴별로 좋아하지 않아요, 인정해야한다. 어색하고 불규칙하게 보입니다. 필자는 가능한 한 객체 유형을 피하고 패키지 (또는 매우 유사한 객체 유형)를 고수 할 것입니다. package-as-fatory는 다른 유형의 공통 코드 리팩토링이 아닌 생성자의 개인 공통 코드 문제를 해결하는 데 도움이됩니다.

... Object Types ....를 사용하는 더 좋은 방법이 없다면 ... 누구입니까? 누군가?

0

이 답변은 다소 어렵지만 가능한 한 최선을 다해 설명하겠습니다. 첫째, 완전히 오라클의 잘못이 아닙니다. ANSI SQL은 SQL을 확장하는 데 사용할 수있는 ADT (Abstract Data Types)라는 것을 정의합니다. 오라클은 스펙을 잘 따르고 있습니다. 캡슐화 부족의 일부는 SQL에서 오브젝트를 참조하고 저장하는 데 어려움이 있습니다. 그러나 나는 그 자체로 완전히 이해하지 못하기 때문에 여기에 세부 사항을 설명하지는 않을 것입니다.

ADT는 코드 나 테이블에서 데이터에 구조를 제공하는 데 유용하지만 매우 복잡하지는 않습니다. 예를 들어 오브젝트 A에 다시 오브젝트 A가있는 오브젝트 B를 가질 수 없습니다. 이는 SQL 테이블에 저장할 수 없습니다. Oracle에서 REF를 사용하여이 문제를 해결할 수 있지만 (다른 공급 업체가이 문제를 어떻게 처리하는지는 확실하지 않음) 코드에서 해결해야 할 또 다른 문제가됩니다.

저는 ADT가 매우 간단한 구조와 매우 간단한 멤버 메소드에 유용하다는 것을 알았습니다. 좀 더 정교하게하려면 패키지가 필요합니다. 종종, 객체 내에서 private 메소드를 호출 할 수 없기 때문에 주어진 객체 유형에 대한 멤버 메소드를 구현하는 패키지를 작성합니다.

그것은 고통 ...

0

그냥 선언 블록에 또 다른 내에서 둥지를 할 수 않는 한 서브 PL/SQL에서 서브 프로그램을 서브 프로그램 (함수/프로 시저)을 사용합니다.

개인적인 메서드 나 함수를 갖는 것만 큼 이상하지는 않지만 상속 계층 구조를 만들기 전에 시도해 볼 가치가 있습니다.

create or replace type body some_t 
as 

member function foo 
    return varchar2 
    as 
     function some_private_foo 
      return varchar2 
      as 
      begin 
       return 'Foo!'; 
      end some_private_foo; 
    begin 
     return some_private_foo(); 
    end foo; 

end; 

오라클 12를 사용하고 있다면 운이 좋을 것입니다. ACCESSIBLY BY 절을 사용하여 유형 만 코딩 할 수있는 패키지를 만들 수 있습니다. 아래 예제에서 PL/SQL 컴파일러는 FOO_T의 코드가 FOO_PRIVATE_PKG를 참조 할 수 있도록 허용합니다.

CREATE OR REPLACE package foo_private_pkg 
accessible by (foo_t) 
as 

function some_private_foo (object_in in out nocopy foo_t) 
    return varchar2; 
end; 
관련 문제