oracle PL/SQL 私有对象方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1580205/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PL/SQL private object method
提问by PrivateMethodMan
I'm a bit new to Oracle's PL/SQL (using 10g), I was wondering if there's a way to make a private method in an object type, as is often done for private helper methods in other languages (Java, C++, C#, etc...). I knowit is possible to make private methods in packages, but I can't seem to find a way to do this for object types. I keep getting compiler errors telling me:
我对 Oracle 的 PL/SQL(使用 10g)有点陌生,我想知道是否有一种方法可以在对象类型中创建私有方法,就像其他语言(Java、C++、C#)中的私有辅助方法通常所做的那样, 等等...)。我知道可以在包中创建私有方法,但我似乎找不到针对对象类型执行此操作的方法。我不断收到编译器错误告诉我:
Error: PLS-00539: subprogram 'FOO' is declared in an object type body and must be defined in the object type specification.
回答by PrivateMethodMan
Ok, here's a potential solution that I tested very briefly, and it seems to work so far:
好的,这是我非常简短地测试过的一个潜在解决方案,到目前为止它似乎有效:
Create a parent object type that will marked as NOT FINAL and NOT INSTANTIABLE and then put all the private code in there. The private methods won't be truly private, but putting them in a type that is not final and not instantiable prevents them from being called. In the instantiable subtype, reference the "private" methods in the supertype through SELF. Example:
创建一个将标记为 NOT FINAL 和 NOT INSTANTIABLE 的父对象类型,然后将所有私有代码放在那里。私有方法不会是真正的私有方法,但将它们放入非 final 且不可实例化的类型可防止它们被调用。在可实例化的子类型中,通过 SELF 引用超类型中的“私有”方法。例子:
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, I don't really like this pattern. It seems awkward and kludgy. I'm probably going to just avoid Object Types as much as I can and stick to packages (or very simlpe object types). A package-as-fatory only helps me solve the private common code problem for constructors, not for other types of common code refactoring.
现在我不得不承认,我真的不喜欢这种模式。看起来很笨拙和笨拙。我可能会尽可能地避免对象类型并坚持使用包(或非常简单的对象类型)。package-as-fatory 只能帮助我解决构造函数的私有公共代码问题,而不是其他类型的公共代码重构。
...unless there's a better way to work with Object Types.... anyone? anyone?
...除非有更好的方法来处理对象类型....有人吗?任何人?
回答by Jon Theriault
If you just need to use the subprogram (function/procedure) from one subprogram PL/SQL does allow you to nest a subprogram within another in the declaration block.
如果您只需要使用一个子程序中的子程序(函数/过程),PL/SQL 确实允许您在声明块中的另一个子程序中嵌套一个子程序。
It's not as ideal as having private methods or functions but it might be worth a try before you go 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 code against using the ACCESSIBLE BY clause. In the example below the PL/SQL compiler will only allow code from FOO_T to reference FOO_PRIVATE_PKG.
如果您使用的是 Oracle 12,那么您很幸运。您可以使用 ACCESSIBLE 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;
回答by tuinstoel
You can't have private methods in pl/sql objects, you can have polymorphism and inheritance but no encapsulation.
pl/sql 对象中不能有私有方法,可以有多态和继承,但不能有封装。
When you want encapsulation (private methods) you can use pl/sql packages.
当您想要封装(私有方法)时,您可以使用 pl/sql 包。
All three at once isn't possible.
不可能同时拥有三个。
回答by djb
The answer to this is somewhat difficult, but I'll explain it as best as I can. First, it's not completely Oracle's fault; ANSI SQL defines a thing called Abstract Data Types (ADT's) which can be used to extend SQL. Oracle follows their specifications pretty well I think. Part of the lack of encapsulation comes with the difficulty of referencing and storing objects in SQL. I won't get into the details here however since I don't fully understand it myself.
这个答案有点困难,但我会尽我所能解释它。首先,这不完全是 Oracle 的错;ANSI SQL 定义了一种称为抽象数据类型 (ADT) 的东西,可用于扩展 SQL。我认为 Oracle 很好地遵循了他们的规范。缺乏封装的部分原因是在 SQL 中引用和存储对象很困难。但是我不会在这里详细介绍,因为我自己并不完全理解。
ADT's are useful to give structure to your data, either in code or in tables, but they can't be very complex. For example, you cannot have Object A that has Object B which again has Object A. This cannot be stored in a SQL table. You can get around this by using REFs in Oracle (not sure how other vendors go about this) but that becomes another problem to solve in code.
ADT 可用于在代码或表格中为您的数据提供结构,但它们不能非常复杂。例如,不能让对象 A 具有对象 B,而对象 B 又具有对象 A。这不能存储在 SQL 表中。您可以通过在 Oracle 中使用 REF 来解决这个问题(不确定其他供应商如何解决这个问题),但这成为另一个需要在代码中解决的问题。
I've found that ADT's are good for very simple structures and very simple member methods. Anything more elaborate requires packages. Often, I'll write a package that implements member methods for a given Object Type, since you can't call private methods inside an object.
我发现 ADT 适用于非常简单的结构和非常简单的成员方法。任何更复杂的东西都需要包。通常,我会编写一个包来实现给定对象类型的成员方法,因为您不能在对象内部调用私有方法。
It is a pain...
这是一种痛苦...