PL/SQL - 面向对象编程
你好,有抱负的程序员们!今天,我们将踏上一段激动人心的旅程,探索PL/SQL中的面向对象编程(OOP)世界。如果你是编程新手,不用担心——我会成为你友好的向导,一步一步地解释所有内容。那么,让我们开始吧!
什么是面向对象编程?
在我们开始之前,让我们了解一下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('John Doe', 30);
DBMS_OUTPUT.PUT_LINE(john.say_hello());
END;
在这个例子中,我们创建了一个person
对象类型,包含两个属性(name
和age
)和一个方法(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('John Doe', 30);
john.have_birthday();
DBMS_OUTPUT.PUT_LINE(john.say_hello());
END;
在这里,我们添加了一个have_birthday
过程,它将人的年龄增加1。这就像给我们的乐高角色赋予了庆祝生日的技能!
使用Map方法
Map方法用于比较对象。它就像给我们的对象一张特殊的身份证,帮助我们排序。让我们看看它是如何工作的:
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('John Doe', 30);
jane person := person('Jane Smith', 25);
BEGIN
IF john > jane THEN
DBMS_OUTPUT.PUT_LINE(john.name || ' 更年长');
ELSE
DBMS_OUTPUT.PUT_LINE(jane.name || ' 更年长');
END IF;
END;
在这个例子中,我们使用age
作为比较的ID。这就像根据乐高角色的身高来比较它们!
使用Order方法
Order方法是比较对象的另一种方式,但它比Map方法提供了更多的灵活性。它就像有一个特殊的裁判来比较我们的乐高角色:
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('John Doe', 30);
jane person := person('Jane Smith', 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('Alice Johnson', 35, 'Manager', 5000);
BEGIN
DBMS_OUTPUT.PUT_LINE(emp.say_hello());
DBMS_OUTPUT.PUT_LINE('年薪: $' || emp.get_annual_salary());
END;
在这里,employee
是person
的子类型,继承了它的属性和方法,同时添加了自己的。就像创建一个特殊的乐高角色,它不仅可以做普通角色能做的一切,还能做得更多!
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('面积 of ' || c.name || ': ' || c.get_area());
END;
在这个例子中,shape
是一个抽象对象,为所有形状定义了一个通用结构。circle
是shape
的具体实现。就像有一个通用的乐高指导手册(抽象对象),然后根据它创建特定的乐高模型!
就是这样!我们已经覆盖了PL/SQL中面向对象编程的基础。记住,熟能生巧,所以不要害怕用这些概念进行实验。快乐编码!
方法 | 描述 |
---|---|
构造函数 | 创建并初始化一个对象 |
成员函数 | 返回一个值,可以在SQL语句中使用 |
成员过程 | 执行一个动作,但不返回值 |
Map方法 | 用于比较对象,基于单个值 |
Order方法 | 用于比较对象,允许自定义比较逻辑 |
FINAL方法 | 不能在子类型中被覆盖 |
NOT INSTANTIABLE方法 | 必须在子类型中被覆盖后才能实例化对象 |
Credits: Image by storyset