PL / SQL Private Object Method
I'm a bit new to Oracle PL / SQL (using 10g), I was wondering if there is a way to make a private method on an object type, as is often done for private helper methods in other languages (Java, C ++, C #, etc.) etc.). I know it is possible to create private methods in packages, but I cannot find a way to do this for object types. I keep getting compiler errors:
Error: PLS-00539: subprogram 'FOO' is declared in an object type body and must be defined in the object type specification.
source to share
Ok, here is a potential solution that I tested very briefly and seems to work so far:
Create a parent object type to be marked NOT FINAL and NOT INSTANTIABLE, and then put all the closed code there. Private methods won't be truly private, but including them in a type that's not final and not instantaneous prevents them from being called. In the current subtype, reference the "private" methods in the supertype via SELF. Example:
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;
Now I have to admit that I don't like this pattern. It seems awkward and awkward. I'm probably going to just avoid object types as much as I can and stick with packages (or very simplex object types). The ratifier package helps me solve a particular problem with common code for constructors and not for other types of code refactorings.
... if there is no better way to work with objects ... anyone? anyone?
source to share
The answer to this question is somewhat tricky, but I will explain it as best I can. First, this is not entirely Oracle's fault; ANSI SQL defines a thing called abstract data types (ADTs) that can be used to extend SQL. I think Oracle follows its specifications. Part of the disadvantage of encapsulation stems from the difficulty of binding and storing objects in SQL. However, I will not go into details as I myself do not understand.
ADTs are useful for giving structure to your data, both in code and in tables, but they can't be very complex. For example, you cannot have object A, which has object B, which again has object A. It cannot be stored in a SQL table. You can work around this using REF in Oracle (not sure how other vendors say it), but it becomes another problem to solve in code.
I've found that ADTs are good for very simple structures and very simple member methods. Anything more complex requires packages. Often I will write a package that implements member methods for a given type of object, since you cannot call private methods inside an object.
It is a pain...
source to share
If you just need to use a subroutine (function / procedure) from one subroutine, PL / SQL allows you to nest a subroutine within another in a declaration block.
This is not as ideal as having private methods or functions, but it might be worth trying before creating an inheritance hierarchy.
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;
If you're on Oracle 12, you're in luck. You can create a package that only your type can use using the ACCESSIBLY BY clause. In the example below, the PL / SQL compiler only allows code from FOO_T to reference 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;
source to share