一、什么是链式调用?
链式调用(Method Chaining)是一种编程风格,允许我们在一个表达式中连续调用多个方法,每个方法返回一个对象,供下一个方法继续使用。
在HALO的过程语言中,我们可以通过对象类型+成员函数实现类似的效果:
emp.getDept().getManager().getName();
二、HALO如何实现链式调用?
HALO提供了对象类型(Object Type)机制,允许我们定义带有属性和方法的“类”,并通过成员函数(Member Function) 返回对象本身或其他对象,从而实现链式调用。
实现条件:
1.使用 CREATE TYPE 定义对象类型;
2.使用 CREATE TYPE BODY 实现成员函数;
3.成员函数需返回对象类型(或另一个对象类型);
4.函数中需显式使用 RETURN SELF 或返回其他对象实例。
三、实战演示:
1. 创建的员工对象类型
REATE OR REPLACE TYPE emp_obj AS OBJECT (emp_id NUMBER,emp_name VARCHAR2(100),salary NUMBER,MEMBER FUNCTION set_name(p_name VARCHAR2) RETURN emp_obj,MEMBER FUNCTION set_salary(p_salary NUMBER) RETURN emp_obj,MEMBER FUNCTION apply_raise(p_percent NUMBER) RETURN emp_obj,MEMBER FUNCTION display RETURN VARCHAR2);/CREATE OR REPLACE TYPE BODY emp_obj ASMEMBER FUNCTION set_name(p_name VARCHAR2) RETURN emp_obj ISBEGINRETURN emp_obj(self.emp_id, p_name, self.salary);END;MEMBER FUNCTION set_salary(p_salary NUMBER) RETURN emp_obj ISBEGINRETURN emp_obj(self.emp_id, self.emp_name, p_salary);END;MEMBER FUNCTION apply_raise(p_percent NUMBER) RETURN emp_obj ISBEGINRETURN emp_obj(self.emp_id, self.emp_name, self.salary * (1 + p_percent/100));END;MEMBER FUNCTION display RETURN VARCHAR2 ISBEGINRETURN 'ID: ' || self.emp_id || ', Name: ' || self.emp_name || ', Salary: $' || self.salary;END;END;/
2. 创建员工集合类型
CREATE OR REPLACE TYPE emp_table AS TABLE OF emp_obj;
3.创建人力资源包
CREATE OR REPLACE PACKAGE BODY simple_hr_pkg ASFUNCTION create_employee(p_id NUMBER, p_name VARCHAR2, p_salary NUMBER) RETURN emp_obj ISBEGINRETURN emp_obj(p_id, p_name, p_salary);END;FUNCTION create_emp_table RETURN emp_table ISBEGINRETURN emp_table();END;FUNCTION add_employee(p_table emp_table, p_emp emp_obj) RETURN emp_table ISv_new_table emp_table := emp_table();BEGIN-- 复制现有员工IF p_table IS NOT NULL THENv_new_table := p_table MULTISET UNION ALL emp_table(p_emp);ELSEv_new_table := emp_table(p_emp);END IF;RETURN v_new_table;END;FUNCTION get_total_salary(p_table emp_table) RETURN NUMBER ISv_total NUMBER := 0;BEGINIF p_table IS NOT NULL THENFOR i IN 1..p_table.COUNT LOOPv_total := v_total + p_table(i).salary;END LOOP;END IF;RETURN v_total;END;FUNCTION get_emp_count(p_table emp_table) RETURN NUMBER ISBEGINRETURN CASE WHEN p_table IS NULL THEN 0 ELSE p_table.COUNT END;END;PROCEDURE apply_bonus(p_table IN OUT emp_table, p_bonus_percent NUMBER) ISBEGINIF p_table IS NOT NULL THENFOR i IN 1..p_table.COUNT LOOPp_table(i) := p_table(i).apply_raise(p_bonus_percent);END LOOP;END IF;END;END simple_hr_pkg;/
4.进行测试
DECLARE-- 测试单个员工的链式调用v_employee emp_obj;-- 测试员工集合v_employees emp_table;v_total_salary NUMBER;v_emp_count NUMBER;BEGINDBMS_OUTPUT.PUT_LINE('=== 链式调用测试 ===');DBMS_OUTPUT.PUT_LINE('');-- 1. 测试单个员工的链式调用DBMS_OUTPUT.PUT_LINE('1. 单个员工链式调用:');v_employee := simple_hr_pkg.create_employee(100, 'John Doe', 50000).apply_raise(10) -- 加薪10%.set_name('John Smith') -- 改名.apply_raise(5); -- 再加薪5%DBMS_OUTPUT.PUT_LINE(' 最终员工信息: ' || v_employee.display());DBMS_OUTPUT.PUT_LINE('');-- 2. 测试员工集合操作DBMS_OUTPUT.PUT_LINE('2. 员工集合操作:');-- 创建员工集合并添加员工v_employees := simple_hr_pkg.create_emp_table();v_employees := simple_hr_pkg.add_employee(v_employees,simple_hr_pkg.create_employee(101, 'Alice', 60000));v_employees := simple_hr_pkg.add_employee(v_employees,simple_hr_pkg.create_employee(102, 'Bob', 70000));v_employees := simple_hr_pkg.add_employee(v_employees,simple_hr_pkg.create_employee(103, 'Charlie', 55000));v_emp_count := simple_hr_pkg.get_emp_count(v_employees);v_total_salary := simple_hr_pkg.get_total_salary(v_employees);DBMS_OUTPUT.PUT_LINE(' 员工数量: ' || v_emp_count);DBMS_OUTPUT.PUT_LINE(' 总薪资: $' || v_total_salary);DBMS_OUTPUT.PUT_LINE('');-- 3. 测试批量操作DBMS_OUTPUT.PUT_LINE('3. 批量薪资调整:');DBMS_OUTPUT.PUT_LINE(' 调整前总薪资: $' || simple_hr_pkg.get_total_salary(v_employees));-- 应用10%奖金simple_hr_pkg.apply_bonus(v_employees, 10);DBMS_OUTPUT.PUT_LINE(' 调整后总薪资: $' || simple_hr_pkg.get_total_salary(v_employees));DBMS_OUTPUT.PUT_LINE('');-- 4. 显示所有员工信息DBMS_OUTPUT.PUT_LINE('4. 所有员工信息:');IF v_employees IS NOT NULL THENFOR i IN 1..v_employees.COUNT LOOPDBMS_OUTPUT.PUT_LINE(' ' || v_employees(i).display());END LOOP;END IF;DBMS_OUTPUT.PUT_LINE('');DBMS_OUTPUT.PUT_LINE('=== 测试完成 ===');END;/

四、总结:链式调用的优势
1. 代码简洁:一条语句完成多个操作,减少中间变量
2. 可读性强:逻辑清晰,贴近自然语言
3. 易于维护:对象封装,结构清晰,修改方便
文章转载自Halo Tech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




