笔者的 ABAP 开发教程 里有一个专题,专门介绍 ABAP 7.40 之后新引入的关键字:
ABAP 7.40 新语法介绍系列之一:ABAP 变量内联声明(Inline Declaration)
ABAP 7.40 新语法介绍系列之二:ABAP 类型转换操作符 CONV
ABAP 7.40 新语法介绍系列之三:ABAP Value 操作符
ABAP 7.40 新语法介绍系列之四:ABAP Table Expression 内表表达式的用法
ABAP 7.40 新语法介绍系列之五:增强的 ABAP OPEN SQL 语法介绍
ABAP 7.40 新语法介绍系列之六:使用 FILTER 关键字对 ABAP 内表进行过滤
ABAP 7.40 新语法介绍系列之七:使用 REDUCE 关键字实现归并聚合操作
其中 BASE 也是这一系列新引入的关键字的一员。
不过在我们开始聊 ABAP 之前,先看下面这段 JavaScript 代码,构造了一个常量对象实例。
{ =
'Jerry', :
30, :
'中国' :
};
把这段代码,直接粘贴到浏览器开发者工具 Console 面板里,敲回车执行:
很简单的代码。
再接着往下看:
const newPerson = {
...originalPerson,
name: "Tom"
};
console.log(`姓名: ${newPerson.name}`);
console.log(`年龄: ${newPerson.age}`);
console.log(`国家: ${newPerson.country}`);
上述这段代码构造了一个新的对象,其中 age 和 country 字段都从旧的对象里拷贝而来,name 字段值则显式指定为新值 Tom.
在上面的例子里,基于 originalPerson 的部分属性,构造新对象的做法,通过三个点 `...` 来完成,这是 JavaScript 里的展开操作符(Spread Operator).
展开运算符用于将一个对象的可枚举属性复制到另一个对象中,从而创建一个新的对象,并在此基础上添加或修改属性。
在对象字面量中,展开运算符用于将一个对象的所有可枚举属性,复制到新的对象中。这使得开发者可以基于现有对象创建新的对象,并对其进行修改或扩展。
展开运算符在 JavaScript 和 TypeScript 开发中有着广泛的用途:
扩展现有对象:基于已有对象,创建新的对象,并对特定属性进行修改。
合并多个对象:将多个对象的属性合并到一个新的对象中。
浅拷贝对象:创建一个对象的浅拷贝。
比如在笔者从事的 Spartacus 这个开源 Storefront 的项目开发代码中,展开运算符在 908 个文件里总共使用了 3102 次,可以说是一个非常基础的操作符了。
有了 JavaScript 里展开操作符的使用经验,再回过头看 ABAP 的 BASE 操作符,就容易理解了。
笔者上面的 JavaScript 展开操作符的例子,可以用 BASE 完美地复刻。
TYPES: BEGIN OF ty_person,
name TYPE string,
age TYPE i,
country TYPE string,
END OF ty_person.
DATA(original_person) = VALUE ty_person(
name = `Jerry`
age = 30
country = `中国`
).
DATA(new_person) = VALUE ty_person(
BASE original_person
name = `Tom`
).
WRITE: / `姓名: `, new_person-name.
WRITE: / `年龄: `, new_person-age.
WRITE: / `国家: `, new_person-country.
执行后,代码第 15 行生成的 new_person 结构体变量,其 age 和 counry 字段值,来自 BASE 关键字指定的 original_person 中的同名字段,name 值则显式指定成了 Tom.
ABAP 7.40 提出了构造表达式(Constructor Expressions)的概念,允许 ABAP 开发人员通过特定的语法结构,直接在表达式中创建并初始化数据对象的机制。
这种方式从视觉上来说最直观的变化,就是现在 ABAP 开发者,可以在一行代码中完成数据对象的声明和赋值,提升代码的简洁性和可读性。这也是 SAP 官方的 ABAP 编程规范中推荐的用法。
常见的构造表达式包括 NEW、CORRESPONDING 以及本文使用的 VALUE 关键字,它们广泛用于初始化数据对象、创建类实例,以及在结构或内表之间进行同名字段的值传递。
本文这个例子,展示了 JavaScript 和 ABAP 二者对同一语言特性,设计了视觉效果截然不同的两种标识符:... vs BASE,仔细想想也是一件很有意思的事情。
为什么会有这种差异?以下是笔者个人看法,不代表 SAP 官方观点。
JavaScript 于 1995 年诞生于网景公司,其主要目的是为浏览器提供一种轻量级的脚本语言,使开发者能够快速地在网页中实现动态交互功能。随着时间的推移,JavaScript 逐渐进化为一门前后端通吃的全栈语言,不仅统治了前端开发领域,也将触角通过 Node.js 伸向后端领域。
在 JavaScript 的设计中,简洁性和易用性一直是核心目标。这与 JavaScript 诞生之初的核心受众,即前端开发者的需求密切相关。较低的学习门槛是 JavaScript 的显著特色。比如目前 Github 上涌现出一大批作者为中小学生们的代码仓库。下面就是一个典型的例子:
一个成都七中的初中生,出于兴趣爱好实现的 Win12 UI 页面效果,佩服佩服
JavaScript 选择 ... 的原因可以追溯到语言设计哲学:
直观与简洁:... 使用三个连续点号模拟展开的视觉效果,开发者可以直接联想到"展开"或"分解"的过程。这种符号的选择减少了语义理解的障碍。 减少语法负担:JavaScript 已经是符号密集型语言,避免额外的关键词能够降低开发者的认知负担。例如与 spread 这种完整但仍存在多种解读可能性的单词相比,... 更短小精悍。 语言扩展的自然演进:... 符号来源于原有的 arguments 对象,其在 ES5 中已经被用于收集剩余参数的功能(rest 参数). 将其复用为展开操作符是一件水到渠成的事情。
function sum(...args) {
return args.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3)); // 打印输出:6
这一设计延续了语法的一致性,使开发者在理解 rest 参数后,能够快速掌握展开操作符的用法。
而 ABAP 作为一门企业级应用开发语言,强调代码的可读性、稳定性、严谨性和对复杂业务场景的支持。
选择 BASE 作为展开操作符的表示形式,也和 ABAP 这门语言的特点分不开:
语义的明确性:BASE 通过其字面的英文单词含义,暗示了其作用是基于某个基础结构进行扩展,便于开发者记忆和阅读。
避免符号滥用:ABAP 的用户群体,主要是熟悉传统企业级应用的开发者,其语言风格倾向于使用清晰明了的关键词,而非 JavaScript 这种轻灵飘逸的符号化语法。ABAP 的语法早已定型,新引入的关键字大多都是语义上可读的英文单词。如果直接照搬 JavaScript 的 ... 符号化语法,显得非常突兀。
更多阅读