Halo Tech

HALO过程语言中的链式调用

一、什么是链式调用?

链式调用(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 AS    MEMBER FUNCTION set_name(p_name VARCHAR2) RETURN emp_obj IS    BEGIN        RETURN emp_obj(self.emp_id, p_name, self.salary);    END;     MEMBER FUNCTION set_salary(p_salary NUMBER) RETURN emp_obj IS    BEGIN        RETURN emp_obj(self.emp_id, self.emp_name, p_salary);    END;    MEMBER FUNCTION apply_raise(p_percent NUMBER) RETURN emp_obj IS    BEGIN        RETURN emp_obj(self.emp_id, self.emp_name, self.salary * (1 + p_percent/100));    END;    MEMBER FUNCTION display RETURN VARCHAR2 IS    BEGIN        RETURN '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 AS    FUNCTION create_employee(p_id NUMBER, p_name VARCHAR2, p_salary NUMBER) RETURN emp_obj IS    BEGIN        RETURN emp_obj(p_id, p_name, p_salary);    END;
    FUNCTION create_emp_table RETURN emp_table IS    BEGIN        RETURN emp_table();    END;
    FUNCTION add_employee(p_table emp_table, p_emp emp_obj) RETURN emp_table IS        v_new_table emp_table := emp_table();    BEGIN        -- 复制现有员工        IF p_table IS NOT NULL THEN            v_new_table := p_table MULTISET UNION ALL emp_table(p_emp);        ELSE            v_new_table := emp_table(p_emp);        END IF;        RETURN v_new_table;    END;      FUNCTION get_total_salary(p_table emp_table) RETURN NUMBER IS        v_total NUMBER := 0;    BEGIN        IF p_table IS NOT NULL THEN            FOR i IN 1..p_table.COUNT LOOP                v_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 IS    BEGIN        RETURN 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) IS    BEGIN        IF p_table IS NOT NULL THEN            FOR i IN 1..p_table.COUNT LOOP                p_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;BEGIN    DBMS_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 THEN        FOR i IN 1..v_employees.COUNT LOOP            DBMS_OUTPUT.PUT_LINE('   ' || v_employees(i).display());        END LOOP;    END IF;
    DBMS_OUTPUT.PUT_LINE('');    DBMS_OUTPUT.PUT_LINE('=== 测试完成 ===');END;/
Image

四、总结:链式调用的优势

1. 代码简洁:一条语句完成多个操作,减少中间变量

2. 可读性强:逻辑清晰,贴近自然语言

3. 易于维护:对象封装,结构清晰,修改方便