3.3 継承を使用するPL/SQLでのオーバーロードの使用
オーバーロードを使用すると、サブタイプの値を仮パラメータ、つまりスーパータイプに代入できます。この機能を代入性といいます。
オーバーロードおよび代入性については、次のルールがあります。
代入のルール
オーバーロードされたプロシージャの複数のインスタンスがプロシージャ・コールに一致する場合、次の代入ルールによって、コールされるプロシージャが判断されます。
-
オーバーロードされたプロシージャのシグネチャの唯一の違いが、一部のパラメータが同じスーパータイプ・サブタイプ階層のオブジェクト・タイプである場合、最も近い一致が使用されます。最も近い一致とは、サブタイプとスーパータイプの間の継承の深さによって判断され、少なくともすべてのパラメータが他のオーバーロードされたインスタンスと同程度に近く、少なくとも1つのパラメータがより近いことをいいます。
-
オーバーロードされた2つのメソッドのインスタンスが一致したが、1つ目のオーバーロードされたプロシージャにおいていくつかの引数の型が近く、2つ目のプロシージャにおいて他の引数の型が近い場合、セマンティック・エラーが発生します。
-
オブジェクト型階層内でいくつかのパラメータの位置が異なり、かつ他のパラメータはデータ型が異なるために暗黙的な変換が必要になる場合も、セマンティック・エラーが発生します。
3.3.1 継承によるPL/SQLファンクションの解決
継承によるPL/SQLファンクションの解決では、代入のルールに従います。
例3-9では、super_tから始まる3つのレベルを持つ型階層を作成します。ファンクションのオーバーロードされたインスタンスが2つ含まれるパッケージがあります。これらのインスタンスは、型階層内の引数型の位置以外は同じです。起動では、型final_tの変数を宣言してから、オーバーロードされたファンクションをコールします。
階層内でsub_tはsuper_tよりもfinal_tに近いため、実行されるファンクションのインスタンスは、sub_tパラメータを受け入れるインスタンスです。これは、代入のルールに基づいたものです。
コールするインスタンスはコンパイル時に決定されるため、渡された引数もfinal_tであったという事実は無視されることに注意してください。宣言がv super_t := final_t(1,2,3)であれば、引数がsuper_tのオーバーロードされたファンクションがコールされます。
例3-9 PL/SQLファンクションと継承の解決
CREATE OR REPLACE TYPE super_t AS OBJECT (n NUMBER) NOT final; / CREATE OR REPLACE TYPE sub_t UNDER super_t (n2 NUMBER) NOT final; / CREATE OR REPLACE TYPE final_t UNDER sub_t (n3 NUMBER); / CREATE OR REPLACE PACKAGE p IS FUNCTION func (arg super_t) RETURN NUMBER; FUNCTION func (arg sub_t) RETURN NUMBER; END; / CREATE OR REPLACE PACKAGE BODY p IS FUNCTION func (arg super_t) RETURN NUMBER IS BEGIN RETURN 1; END; FUNCTION func (arg sub_t) RETURN NUMBER IS BEGIN RETURN 2; END; END; / DECLARE v final_t := final_t(1,2,3); BEGIN DBMS_OUTPUT.PUT_LINE(p.func(v)); -- prints 2 END; /
関連項目:
「継承を使用するPL/SQLでのオーバーロードの使用」を参照してください
3.3.2 継承によるPL/SQLファンクションの動的解決
継承によるPL/SQLファンクションの動的解決では、代入のルールに従います。
「継承を使用するPL/SQLでのオーバーロードの使用」を参照してください
例3-10では、ファンクションは型階層のメンバー・ファンクションをオーバーライドしているため、コールするインスタンスは実行時に決定されます。これは、「動的メソッド・ディスパッチ」で説明されている動的メソッド・ディスパッチです。
vはsuper_tのインスタンスですが、final_tの値がvに割り当てられているため、代入のルールに従ってファンクションのsub_tインスタンスがコールされます。
例3-10 PL/SQLファンクションと継承の動的解決
-- Perform the following drop commands if you created these objects in Ex. 3-9
-- DROP PACKAGE p;
-- DROP TYPE final_t;
-- DROP TYPE _sub_t;
-- DROP TYPE super_t FORCE;
CREATE OR REPLACE TYPE super_t AS OBJECT
(n NUMBER, MEMBER FUNCTION func RETURN NUMBER) NOT final;
/
CREATE OR REPLACE TYPE BODY super_t AS
MEMBER FUNCTION func RETURN NUMBER IS BEGIN RETURN 1; END; END;
/
CREATE TYPE sub_t UNDER super_t
(n2 NUMBER,
OVERRIDING MEMBER FUNCTION func RETURN NUMBER) NOT final;
/
CREATE OR REPLACE TYPE BODY sub_t AS
OVERRIDING MEMBER FUNCTION func RETURN NUMBER IS BEGIN RETURN 2; END; END;
/
CREATE OR REPLACE TYPE final_t UNDER sub_t
(n3 NUMBER);
/
DECLARE
v super_t := final_t(1,2,3);
BEGIN
DBMS_OUTPUT.PUT_LINE('answer:'|| v.func); -- prints 2
END;
/