暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

HALO过程语言中的链式调用

Halo Tech 2025-11-13
37

一、什么是链式调用?

链式调用(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;
            /

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

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

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

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

            文章转载自Halo Tech,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

            评论