倉頡編程語言是華為自主研發的一種面向全場景應用開發的現代編程語言,具有高效編程、安全可靠、輕松并發和卓越性能等特點。本節將簡單介紹倉頡語言的部分語法和使用,幫助開發者快速上手。
1.3.1:數據類型
- 整數
倉頡把整數分為有符號和無符號兩種類型,有符號整數用 Int8
、Int16
、Int32
、Int64
和 IntNative
來表示,無符號整數用 UInt8
、UInt16
、UInt32
、UInt64
和 UIntNative
來表示。
var count1: Int8 = 6 // 聲明count1為Int8類型
var count2: Int64 = 6 // 聲明count2為Int64類型
var count3 = 6 // count3無指定類型時默認推導為Int64類型
if (count3 is Int64) {println("count3是Int64類型"); // 輸出count3是Int64類型
}
📢:具體使用哪種類型取決于該程序中需要處理的整數的性質和范圍。在 Int64
類型適合的情況下,首選 Int64
類型。具體范圍可參見官網。
- 小數
倉頡提供了 Float16
、Float32
和 Float64
分別表示編碼長度為 16-bit
、 32-bit
和 64-bit
的小數。
var count1: Float32 = 3.14 // 聲明count1為Float32類型
var count2: Float64 = 3.14 // 聲明count2為Float64類型
var count3 = 3.14 // 聲明count3為默認類型if (count3 is Float64) {println("默認是Float64類型"); // 輸出默認是Float64類型
}
if (count3 == count2) {println("count3 == count2"); // 輸出count3 == count2
}
📢:在多種浮點類型都適合的情況下,首選精度高的浮點類型 Float64
。具體范圍可參見官網。
- Bool
倉頡提供了 Bool
關鍵字來表示邏輯值 true
和 false
。
let a: Bool = true
let b: Bool = false
- Rune
倉頡提供了 Rune
關鍵字來表示字符,格式為:r"*"
或者 r'*'
的形式。
var char1: Rune = r'a'
var char2 = r"a"if(char1 is Rune) {println("char1 is Rune") // 輸出char1 is Rune
} else {println("char1 isn't Rune")
}
if (char1 == char2) {println("char1 == char2") // 輸出char1 == char2
} else {println("char1 != char2")
}
- String
倉頡提供了 String
關鍵字來表示字符串類型,使用單引號('
)或雙引號("
)來表示字符串類型,同時支持插值字符串的表達形式,如 ${a + b}
。
let fruit = "apples"
let count = 10
let s = "There are ${count * count} ${fruit}"
- Array
倉頡使用 Array
關鍵字來表示單一類型的有序數組。
var array1: Array<String> = ["1", "2", "3"]
var array2 = [1, 2, 3]println(array1[2])for (e in array2) {println("the element is ${e}")
}
- 元組
倉頡提供了元組來表示已知元素數量和類型的數組,元組內的各元素的類型不必相同,但是對應位置的類型必須一致。
var tuple1: (Bool, Float64, String) = (false, 3.14, "cj") // 定義元組tuple1并制定類型
var tuple2 = (123, true, 3.14) // 定義元組tuple2由編譯器推導類型
println(tuple1[0]) // 訪問元組,輸出false
println(tuple2[2]) // 訪問元組,輸出3.140000
- Unit
Unit
是一種特殊的數據類型,適用于只關心副作用而不關心值的表達式,例如,println
函數、賦值表達式、復合賦值表達式、自增和自減表達式、循環表達式,它們的類型都是 Unit
。
main(): Int64 {println("unit")testUnit()return 0
}func testUnit(): Unit {var age = 20age++
}
- Any
倉頡提供了 Any
接口,它是一個空實現,所有數據均實現了該接口,因此 Any
可作為一種數據類型來看待。
var data: Any = 12; // 定義data為Any類型,默認賦值12if (data is Int64) { // 判斷是否是Int64類型log("data is Int64") // 輸出data is Int64let value = (data as Int64).getOrDefault({=> -1}) // 取出data內部的值log("value: ${value}") // 輸出value: 12
}data = 3.14 // 給data賦值小數
data = true // 給data賦值Bool
1.3.2:變量聲明
變量在使用前必須先聲明,倉頡可以使用 var
、let
、const
修飾符來聲明一個變量,格式如下:
修飾符 變量名: 變量類型 = 初始值
修飾符 變量名 = 初始值
- var
var
修飾的變量屬于可變變量,允許在運行時對變量的值做修改。
var osName: String = "OpenHarmony"
var price1: Int64 = 5
var price2: Float64 = 5.5
var sum = Float64(price1) + price2
println("操作系統名稱:${osName}") // 操作系統名字: OpenHarmony
println("第一個價格是:${price1}") // 第一個價格是: 5
println("第二個價格是:${price2}") // 第二個價格是: 5.5
println("總價格:${sum}") // 總價格: 10.5price1 = 3 // 重置price1的值
price1 = 3.5 // 編譯報錯,只能賦值Int64類型的值
osName = "HarmonyOS" // 重置osName的值
- let
let
修飾的變量要求在運行時初始化完畢后不可修改。
let age = 20 // age初始化后不可修改
let pi: Float64 = 3.141592653 // pi初始化后不可修改
pi = 5 // 編譯時會報錯
- const
const
修飾的變量要求在編譯期完成求值,并且在運行時不可修改。
const PI = 3.1415926 // 編譯期確定了PI的值
PI = 10 // 報錯,不允許修改
1.3.3:函數
- 函數聲明
函數就是包裹在花括號中的代碼塊,前邊使用 func
關鍵字,語法格式如下:
func function_name() {// 執行代碼
}
例如聲明函數如下:
func log(msg: String) { // 聲明一個函數println(msg); // 代碼塊
}
- 函數調用
函數只有通過調用才可以執行函數內的代碼,語法格式如下:
function_name()
樣例如下:
func log(msg: String) { // 聲明一個函數println(msg); // 代碼塊
}
log("Hello, 倉頡"); // 調用函數
- 函數返回值
如果希望得到函數的執行結果,可以使用 return
語句,語法如下:
func function_name(): return_type {return value; // return語句
}
樣例如下:
func sayHi(): String { // 定義sayHi函數,該函數的返回類型為stringreturn "Hello!"
}func execute() { // 定義execute函數var msg = sayHi(); // 調用sayHi()函數log(msg); // 打印sayHi()函數的返回值
}execute(); // 調用execute()函數
- 帶參數函數
在調用函數時可以向函數傳遞值,這些值被稱為參數,語法如下:
func func_name(param1: paramType, param2: paramType) {
}
樣例如下:
func add(x: Int64, y: Int64): Int64 { // 定義add函數,該函數返回類型為nubmer, 接收兩個number類型的參數xreturn x + y;
}log("${add(1,2)}") // 3
- 命名參數
函數定義了參數則必須傳遞這些參數否則報錯,如果不想傳遞這些參數可以使用命名參數,當不傳入該參數時則使用默認值,語法如下:
func func_name(param1: paramType, param2!: paramType = default_value) {
}
樣例如下:
func add(x: Int64 = 20, y!: Int64 = 50) { // 設置y有默認值return x + y;
}log("${add(10)}"); // y使用默認值,輸出60
log("${add(10, y: 10)}"); // y使用10,輸出20
📢:如果參數不全是命名參數,那么命名參數的位置必須放在最后。
- 變長參數
在不確定要向函數傳遞多個參數的情況下,可以使用變長參數,變長參數前邊以 Array
表示,語法如下:
func func_name(param1: paramType, param2: paramType, param3: Array<paramType>) {
}
樣例如下所示:
func add(param1: String, param2: Array<Int64>): Int64 { // 變長參數log("add: ${param1}");var sum = 0for (e in param2) { // 遍歷剩余參數sum += e}return sum
}log("${add("sum", 1, 2, 3, 4)}") // add: sum// 10
1.3.4:類
- 定義類
倉頡是面向對象的編程語言,定義一個類使用關鍵字 class
,類可以包含字段、構造方法和方法。語法如下:
class class_name {// 類作用域
}
樣例如下:
class Person {var name: String;var age: Int;init(name: String, age: Int) {this.name = name;this.age = age;}func info(): String {return "name: ${this.name}, age: ${this.age}";}
}
- 創建類對象
類定義完后,可以通過 類名(args)
的格式實例化一個類的對象,實例化類對象即調用類的構造方法,語法如下:
var object_name = class_name([ args ])
樣例如下:
var person = Person('張三', 20); // 創建一個Person對象
- 訪問類屬性和方法
訪問類的屬性和方法以 .
號的形式,語法如下:
obj.field_name // 訪問屬性
obj.function_name() // 訪問方法
樣例如下:
var person = Person('harmony', 10); // 創建一個personlog(person.name); // harmony
log("${person.age}"); // 10
log(person.info()); // name: harmony, age: 10
- 類的繼承
倉頡支持繼承類,創建類的時候可以使用 <:
符號繼承一個已有的類,這個已有的類稱為父類,繼承它的類稱為子類。子類除了不能繼承父類的私有成員(方法和屬性)和構造函數,其他的都可以繼承。語法如下:
class child_class_name <: parent_class_name {
}
樣例如下:
open class Person { // 父類使用open關鍵字修飾,表示允許子類繼承var name: Stringvar age: Intinit(name: String, age: Int) {this.name = namethis.age = age}func info(): String {return "name: ${this.name}, age: ${this.age}"}
}class Zhangsan <: Person { // 子類繼承父類init(name: String, age: Int) {super(name, age)}func sayHello() {println("Hello")}
}var person = Zhangsan("張三", 20); // 創建一個person
person.sayHello() // Hello
log(person.name); // 張三
log("${person.age}"); // 20
log(person.info()); // name: 張三, age: 20
📢:父類必須使用 open
關鍵字修飾,并且類的繼承只支持單繼承,不支持多繼承。也就是說子類只能繼承一個父類。
- 方法重寫
子類可以重寫父類的方法,在重寫父類方法的時候也可以使用 super
關鍵字調用父類的方法。樣例如下:
open class Person { // 父類使用open關鍵字修飾,表示允許子類繼承var name: Stringvar age: Intinit(name: String, age: Int) {this.name = namethis.age = age}func info(): String {return "name: ${this.name}, age: ${this.age}"}
}class Zhangsan <: Person { // 子類繼承父類init(name: String, age: Int) {super(name, age)}override func info(): String { // 重寫父類方法return "Hello, " + super.info() // 調用父類方法}
}var person = Zhangsan("張三", 20); // 創建一個person
log(person.info()); // Hello, name: 張三, age: 20
- 訪問修飾符
倉頡提供了訪問控制符來保護對類、變量、方法和構造方法的訪問。它支持 4 種不同的訪問權限。
- internal(默認):受保護,僅當前包及子包內訪問。
- protected:受保護,只能在當前模塊和其子類訪問。
- private:私有,只能在 class 內訪問。
- public:公有,可以在任何地方被訪問。
樣例如下所示:
class Person {var name: String;private var age: Int; // age為private,外界無法訪問init(name: String, age: Int) {this.name = name;this.age = age;}func info(): String {return "name: ${this.name}, age: ${this.age}"}
}var person = Person('harmony', 10); // 創建Person對象
log(person.name); // harmony
log("${person.age}"); // 編譯報錯,age為private
1.3.5:接口
- 定義接口
接口是一系列抽象方法的聲明,接口定義后需要具體的類實現,語法如下:
interface interface_name {// 抽象方法
}
樣例如下:
interface IPerson { // 定義一個接口func say(): Unit // 定義say方法,該方法默認是public,返回值為Unit類型
}
- 接口繼承
接口可以使用 <:
符號繼承其它接口來擴展自己,接口既支持單繼承又支持多繼承,多繼承時接口間使用逗號 &
分隔。語法如下:
// 接口單繼承
interface Child_interface_name <: super_interface_name {
}// 接口多繼承
interface Child_interface_name <: super_interface_name1 & super_interface_name2 {
}
樣例如下:
interface IPlay { // 定義IPlay接口func play(): Unit
}interface IRun { // 定義IRun接口func run(): Unit
}interface ITeacher <: IPlay & IRun { // 定義ITeacher接口,并繼承IPlay和IRun接口func teach(): Unit
}
- 類實現接口
類可以使用 <:
關鍵字實現一個接口,一個類實現接口后必須實現接口定義的方法,語法如下:
class class_name <: interface_name {
}
樣例如下所示:
interface IPlay { // 定義IPlay接口func play(): Unit // 定義play方法
}interface IRun { // 定義IRun接口func run(): Unit // 定義run方法
}interface ITeacher <: IPlay & IRun { // 定義ITeacher接口并繼承IPlay和IRun接口func teach(): Unit // 定義teach方法
}class Teacher <: ITeacher { // 類Teacher實現ITeacher接口public func teach(): Unit { // 實現方法println("teach")}public func play(): Unit { // 實現方法log("play")}public func run(): Unit { // 實現方法log("run")}
}let teacher = Teacher() // 創建Teacher實例
teacher.play() // 輸出play
teacher.run() // 輸出run
teacher.teach() // 輸出teach
1.3.6:擴展
- 直接擴展
倉頡支持對已經存在的類做直接擴展,常用在擴展方法的場景,語法如下:
extend class_name {func func_name(): return_type {} // 添加擴展方法
}
樣例如下:
class Teacher { // 定義Teacher類public var name: String // 添加name屬性public var age: Int // 添加age屬性init(name!: String = "lisi", age!: Int64 = 30) { // 添加構造方法并初始化屬性this.name = namethis.age = age}func teach(): Unit { // 添加teach方法println("teach")}
}extend Teacher { // 對Teacher進行擴展func updateInfo(name: String, age: Int): Unit { // 給Teacher添加updateInfo()方法this.name = namethis.age = age}func printInfo() { // 給Teacher添加printInfo()方法println("teacher info, name = ${this.name}, age = ${this.age}")}
}let teacher = Teacher()
teacher.printInfo() // teacher info, name = lisi, age = 30
teacher.updateInfo("lisi", 18)// 更改信息
teacher.printInfo() // teacher info, name = lisi, age = 18
- 接口擴展
倉頡支持對已經存在的類做接口擴展,它既可以擴展方法,也可以擴展屬性,步驟如下:
-
定義接口
interface interface_name {func method_name(): return_typemut prop prop_name: prop_typeprop prop_name: prop_type }
樣例如下所示:
interface IInfo { // 定義IInfo接口func info(): Unit // 定義info方法mut prop address: String // 定義address屬性prop email: String // 定義email屬性 }
📢:此處的
mut
表示允許給address
賦值。 -
實現擴展
extend class_name <: interface_name {public mut prop prop_name: prop_type {get() {prop_type}set(value) {// 賦值操作}}public prop prop_name: prop_type {get() {prop_type}}public func func_name(): return_type {} }
樣例如下所示:
extend Teacher <: IInfo {public mut prop address: String {get() {"Beijing"}set(value) {address = value}}public prop email: String {get() {"arkui.club@cj.com"}}public func info(): Unit {println("teacher info, name = ${this.name}, age = ${this.age}, address = ${address}")} }
完整樣例如下所示:
package arkui_cjclass TeacherA {public var name: Stringpublic var age: Intinit(name!: String = "lisi", age!: Int64 = 30) {this.name = namethis.age = age}func teach(): Unit {println("teach")}
}extend TeacherA {func updateInfo(name: String, age: Int): Unit {this.name = namethis.age = age}func printInfo() {println("teacher info, name = ${this.name}, age = ${this.age}")}
}interface IInfo {func info(): Unitmut prop address: Stringprop email: String
}extend TeacherA <: IInfo {public mut prop address: String {get() {"Beijing"}set(value) {address = value}}public prop email: String {get() {"arkui.club@cj.com"}}public func info(): Unit {println("teacher info, name = ${this.name}, age = ${this.age}, address = ${address}")}
}main(): Int64 {let teacher = TeacherA()teacher.teach()teacher.printInfo()teacher.updateInfo("Zhangsan", 18)teacher.printInfo()teacher.info()teacher.address = "Shanghai"teacher.info()println(teacher.email)return 0
}
1.3.7:小結
本節簡單介紹了倉頡基礎語法部分,掌握這些基礎部分可以支撐日常簡單應用開發了。對于倉頡更多其它用法,讀者請參考官網。
通過以上介紹,希望你對倉頡編程語言有了一個初步的了解,并能夠開始編寫簡單的HarmonyOS應用。隨著你對倉頡的深入學習,你將能夠更高效地利用其強大功能,開發出更加豐富和高質量的應用。