使用 Harbour/Harbour 开发应用程序概述
与旨在一次编写,随处运行的 Java 不同,Harbour 旨在实现 **一次编写,随处编译**。由于所有上述操作系统都提供相同的编译器,因此无需重新编码即可为不同平台生成相同的产品,除非使用依赖于操作系统的功能。交叉编译通过 MinGW32 支持。在 Microsoft Windows 下,Harbour 比 Clipper 更稳定,但文档较少,但具有跨平台功能,更透明,可定制,并且可以从 USB 闪存驱动器运行。
在 Linux 和 Windows Mobile 下,Clipper 源代码可以经过很少的调整,就可以使用 Harbour 编译。大多数最初编写用于在 Xbase++、Flagship、FoxPro、xHarbour 和其他方言上运行的软件都可以通过 Harbour 编译,只需进行一些调整。到 2010 年,已经做出很多努力来简化从其他 xBase 方言的过渡。
Harbour 可以使用以下 C 编译器,包括但不限于:GCC、MinGW、Clang、ICC、Microsoft Visual C++ (6.0+)、Borland C++、Watcom C、Pelles C 和 Sun Studio。
Harbour 可以使用多种图形终端仿真,包括控制台驱动程序和混合控制台/GUI,例如 GTWvt 和 GTWvg。
Harbour 支持外部 GUI,包括免费的(例如 HWGui、MiniGUI 和 Qt)和商业的(例如 FiveWin、Xailer)。HBQt 是一个为 Qt 提供绑定的库。HBIDE 应用程序包含在官方发行版和 SVN 存储库中,是 HBQt 潜力的一个例子。
Harbour 与 Clipper 100% 兼容[1],并支持许多语言语法扩展,包括大大扩展的运行时库,例如 OLE、Blat、OpenSSL、FreeImage、GD、TIP、Tpathy、PCRE、HbZip(zlib 和 bzip2)、cURL、Cairo、其自身的 CA-Tools 实现和 NanFor 库,以及许多其他库。Harbour 拥有一个活跃的开发社区和广泛的第三方支持。
任何 xBase 语言都提供了一种非常有效的方式来构建业务和数据密集型应用程序。Harbour 也不例外。
xBase 语言最强大的功能之一是 宏 运算符 '&'。Harbour 对宏运算符的实现允许对任何有效的 Harbour 表达式进行运行时编译。这样的编译表达式可以作为 VALUE 使用,即赋值的右侧(rvalue),但更有趣的是,这样的编译表达式可以用于解析赋值的左侧(lvalue),即 PRIVATE 或 PUBLIC 变量,或数据库 FIELD。
此外,宏运算符可以编译和执行函数调用,完成赋值,甚至执行参数列表,并且宏的结果可以用于解析编译应用程序中的任何上述上下文。换句话说,任何 Harbour 应用程序都可以扩展并在运行时进行修改,以按需编译和执行额外的代码。
最新的宏编译器可以编译任何有效的 Harbour 代码,包括在编译之前进行预处理的代码。
语法
&( ... )
表达式的文本值 '...' 将被编译,并且执行编译代码后产生的值是结果。
&SomeId
是 &( SomeId ) 的简写形式。
&SomeId.postfix
是 &( SomeId + "postfix" ) 的简写形式。
以 OOP 风格编程是一个比特定库或特定接口更广泛的问题,但 OOP 编程是许多 Clipper 程序员所期望的。CA-Clipper 5.2 尤其是 5.3 添加了许多基本类和匹配的 OOP 语法。诸如 CLASSy、Fivewin、Clip4Win 和 TopClass 等库提供了额外的 OOP 功能。
Harbour 具有 OOP 扩展,全面支持基于 CLASSy 语法的类,包括继承。Harbour 中的 OOP 语法与早期 Clipper 类库非常相似,因此可以通过最少的更改来维护遗留的 Clipper 代码。
与所有 xBase 语言一样,Harbour 不区分大小写,并且可以选择接受仅用前四个字符书写的关键字。
Harbour 有 6 种标量类型:Nil、字符串、日期、逻辑、数字、指针,以及 4 种复杂类型:数组、对象、代码块 和 哈希。标量保存单个值,例如字符串、数字或对任何其他类型的引用。数组是有序的标量或复杂类型列表,通过数字索引,从 1 开始。哈希或 关联数组 是任何类型值的无序集合,通过其关联的键索引,该键可以是任何标量或复杂类型。
标量类型的字面量(静态)表示
- Nil:NIL
- 字符串:"hello",'hello',[hello]
- 日期:0d20100405
- 逻辑:.T.,.F.
- 数字:1,1.1,-1,0xFF
复杂类型也可以表示为字面量值
- 数组:{ "字符串",1,{ "嵌套数组" },.T.,FunctionCall(),@FunctionPointer() }
- 代码块:{ |Arg1,ArgN| Arg1 := ArgN + OuterVar + FunctionCall() }
- 哈希:{ "姓名" => "John",1 => "数字键",{ "嵌套" => "哈希" } }
哈希可以使用 *任何* 类型,包括其他哈希作为任何元素的 *键*。哈希和数组可以包含 *任何* 类型作为任何成员的 *值*,包括嵌套数组和哈希。
代码块可以引用定义它的过程/函数 > 方法的变量。这样的代码块可以作为值返回,或者通过引用传递的参数,在这种情况下,代码块将“超出”定义它的例程,并且它引用的任何变量都将成为 *分离的* 变量。
分离的变量将保留其值,只要引用它们的代码块仍然存在。这些值将与任何其他可能访问相同变量的代码块共享。如果代码块没有超出其包含的例程,并且将在定义它的例程的生命周期内进行评估,则通过评估 *分离的变量*(s) 的更改将反映回其父例程。
代码块可以通过 Eval( *BlockExp* ) 函数进行多次评估。
所有类型都可以分配给命名变量。命名变量标识符长度为 1 到 63 个字符,以 [A-Z|_] 开头,并且包含 [A-Z|0-9|_] 字符,最多 63 个字符。命名变量不区分大小写。
变量具有以下范围之一
- LOCAL:仅在声明它的例程内可见。值在例程退出时丢失。
- STATIC:仅在声明它的例程内可见。该值会保留以供后续调用该例程。如果在定义任何过程/函数/方法之前声明了 STATIC 变量,则它具有模块范围,并且在该同一源文件中定义的任何例程内可见,它将为应用程序生命周期持续时间保持其生命周期。
- PRIVATE:在声明它的例程及其调用的例程内可见。
- PUBLIC:对同一应用程序中的所有例程可见。
LOCAL 和 STATIC 在编译时解析,因此比通过运行时符号表访问的动态实体PRIVATE 和 PUBLIC 变量快得多。出于同样的原因,LOCAL 和 STATIC 变量不会暴露给宏编译器,任何尝试引用它们的宏代码都会生成运行时错误。
由于PRIVATE 和 PUBLIC 变量的动态特性,它们可以在运行时创建和销毁,可以通过运行时宏访问和修改,并且可以通过动态创建的代码块访问和修改。