PL/SQL - オブジェクト指向プログラミング

こんにちは、志を抱くプログラマーたち!今日は、PL/SQLにおけるオブジェクト指向プログラミング(OOP)の楽しい旅に出発します。プログラミングが新しい方も心配しないでください。私はあなたのフレンドリーなガイドとして、すべてをステップバイステップで説明します。それでは、さっそく始めましょう!

PL/SQL - Object Oriented

オブジェクト指向プログラミングとは?

まず、OOPとは何についているのかを理解しましょう。レゴブロックで家を建てることを想像してください。それぞれのブロックはオブジェクトを表し、これらのブロックをさまざまな方法で組み合わせて複雑な構造を作成できます。それは基本的に、プログラミングにおけるOOPがやっていることです。現実の実体を表すオブジェクトを作成し、操作することを可能にします。

オブジェクトのインスタンス化

それでは、PL/SQLでオブジェクトを作成(または「インスタンス化」)する方法を学びましょう。レゴキャラクターをプログラミングの世界で生き返らせることに例えましょう!

CREATE OR REPLACE TYPE person AS OBJECT (
name VARCHAR2(50),
age NUMBER,
MEMBER FUNCTION say_hello RETURN VARCHAR2
);

CREATE OR REPLACE TYPE BODY person AS
MEMBER FUNCTION say_hello RETURN VARCHAR2 IS
BEGIN
RETURN 'こんにちは、私の名前は ' || name || ' で、年齢は ' || age || '歳です。';
END;
END;

DECLARE
john person;
BEGIN
john := person('ジョン・ドー', 30);
DBMS_OUTPUT.PUT_LINE(john.say_hello());
END;

この例では、personオブジェクトタイプを作成し、2つの属性(nameage)とメソッド(say_hello)を定義しています。そしてオブジェクトjohnをインスタンス化し、そのsay_helloメソッドを呼び出しています。

メンバーメソッド

メンバーメソッドは、オブジェクトが持つ特別なスキルです。personオブジェクトに別のメソッドを追加してみましょう:

CREATE OR REPLACE TYPE person AS OBJECT (
name VARCHAR2(50),
age NUMBER,
MEMBER FUNCTION say_hello RETURN VARCHAR2,
MEMBER PROCEDURE have_birthday
);

CREATE OR REPLACE TYPE BODY person AS
MEMBER FUNCTION say_hello RETURN VARCHAR2 IS
BEGIN
RETURN 'こんにちは、私の名前は ' || name || ' で、年齢は ' || age || '歳です。';
END;

MEMBER PROCEDURE have_birthday IS
BEGIN
age := age + 1;
DBMS_OUTPUT.PUT_LINE(name || ' は今 ' || age || '歳になりました。');
END;
END;

DECLARE
john person;
BEGIN
john := person('ジョン・ドー', 30);
john.have_birthday();
DBMS_OUTPUT.PUT_LINE(john.say_hello());
END;

ここでは、have_birthdayプロシージャを追加し、オブジェクトの年齢を1歳増やしています。レゴキャラクターに誕生日を祝う能力を与えるようなものです!

マップメソッドの使用

マップメソッドは、オブジェクトを比較するために使用されます。オブジェクトに特別なIDカードを渡し、それを基に並べ替えることができます。それでは、どうやって動作するかを見てみましょう:

CREATE OR REPLACE TYPE person AS OBJECT (
name VARCHAR2(50),
age NUMBER,
MAP MEMBER FUNCTION get_id RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY person AS
MAP MEMBER FUNCTION get_id RETURN NUMBER IS
BEGIN
RETURN age;
END;
END;

DECLARE
john person := person('ジョン・ドー', 30);
jane person := person('ジーン・スミス', 25);
BEGIN
IF john > jane THEN
DBMS_OUTPUT.PUT_LINE(john.name || ' は年上です');
ELSE
DBMS_OUTPUT.PUT_LINE(jane.name || ' は年上です');
END IF;
END;

この例では、ageをIDとして比較に使用しています。レゴキャラクターを身長で比較するようなものです!

オーダーメソッドの使用

オーダーメソッドは、オブジェクトを比較する別の方法で、マップメソッドよりも柔軟性があります。特別な判定官がレゴキャラクターを比較するようなものです:

CREATE OR REPLACE TYPE person AS OBJECT (
name VARCHAR2(50),
age NUMBER,
ORDER MEMBER FUNCTION compare(p person) RETURN INTEGER
);

CREATE OR REPLACE TYPE BODY person AS
ORDER MEMBER FUNCTION compare(p person) RETURN INTEGER IS
BEGIN
IF self.age < p.age THEN
RETURN -1;
ELSIF self.age > p.age THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
END;
END;

DECLARE
john person := person('ジョン・ドー', 30);
jane person := person('ジーン・スミス', 30);
BEGIN
IF john > jane THEN
DBMS_OUTPUT.PUT_LINE(john.name || ' は年上です');
ELSIF john < jane THEN
DBMS_OUTPUT.PUT_LINE(jane.name || ' は年上です');
ELSE
DBMS_OUTPUT.PUT_LINE('彼らは同じ年齢です');
END IF;
END;

このメソッドは、複数の属性に基づいてオブジェクトを比較する際に特に役立ちます。

PL/SQLオブジェクトの継承

継承は、オブジェクトの家系図を作成するようなものです。既存のオブジェクトからプロパティやメソッドを継承した新しいオブジェクトを作成できます。それでは、見てみましょう:

CREATE OR REPLACE TYPE employee UNDER person (
job_title VARCHAR2(50),
salary NUMBER,
MEMBER FUNCTION get_annual_salary RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY employee AS
MEMBER FUNCTION get_annual_salary RETURN NUMBER IS
BEGIN
RETURN salary * 12;
END;
END;

DECLARE
emp employee := employee('アリス・ジョンソン', 35, 'マネージャー', 5000);
BEGIN
DBMS_OUTPUT.PUT_LINE(emp.say_hello());
DBMS_OUTPUT.PUT_LINE('年間給料: $' || emp.get_annual_salary());
END;

ここでは、employeepersonのサブタイプで、そのプロパティとメソッドを継承しつつ、独自のプロパティとメソッドを追加しています。レゴキャラクターが通常のキャラクター以上のことができる特別なキャラクターを作成するようなものです!

PL/SQLにおける抽象オブジェクト

抽象オブジェクトは、他のオブジェクトの蓝图のようなものです。構造を定義しますが、直接インスタンス化することはできません。抽象オブジェクトを作成してみましょう:

CREATE OR REPLACE TYPE shape AS OBJECT (
name VARCHAR2(50),
MEMBER FUNCTION get_area RETURN NUMBER
) NOT INSTANTIABLE NOT FINAL;

CREATE OR REPLACE TYPE circle UNDER shape (
radius NUMBER,
OVERRIDING MEMBER FUNCTION get_area RETURN NUMBER
);

CREATE OR REPLACE TYPE BODY circle AS
OVERRIDING MEMBER FUNCTION get_area RETURN NUMBER IS
BEGIN
RETURN 3.14159 * radius * radius;
END;
END;

DECLARE
c circle := circle('私の円', 5);
BEGIN
DBMS_OUTPUT.PUT_LINE('円の面積: ' || c.name || ': ' || c.get_area());
END;

この例では、shapeは抽象オブジェクトで、すべての形状に共通する構造を定義しています。circleshapeの具体実装です。一般のレゴ説明書(抽象オブジェクト)に基づいて特定のレゴモデルを作成するようなものです!

そして、ここまででPL/SQLにおけるオブジェクト指向プログラミングの基本をカバーしました。実践が完璧を生むことを忘れないでください。これらの概念を試してみてください。お楽しみに!

Credits: Image by storyset