目录

1.struct 核心概念与定义

2.struct 实例化

3.构造函数的调用约束

4.静态成员变量与静态构造函数

5.struct 的核心特性:值传递

6.struct 的可变控制:mut 关键字与属性设计器

6.1 mut 关键字:修改实例变量的必要条件

6.2 属性设计器

7.struct 综合实践


        在仓颉语言中,struct(结构体) 是用于构建数据模型的核心值类型,相比类(Class),它更轻量、高效,专注于数据封装与值传递。作为鸿蒙原生开发的重要基石,struct 支持自定义方法、属性访问、可变控制等特性,同时在内存布局和性能优化上独具优势。

1.struct 核心概念与定义

  struct是一种值类型,而class引用类型。这意味着当你把一个struct实例赋值给一个新变量时,会创建该实例的一个完整副本。而class的赋值,则是让新变量引用同一个对象实例。struct支持成员变量、成员函数、构造函数、属性等完整的面向对象能力,但不支持继承(Class 支持继承),适用于定义轻量级的数据载体(如坐标、尺寸、用户信息等)。

struct 定义语法

  struct 类型的定义以关键字 struct 开头,后跟 struct 的名字,接着是定义在一对花括号中的 struct 定义体。struct 定义体中可以定义一系列的成员变量、成员属性、静态初始化器、构造函数和成员函数。

示例:定义一个Employee结构体

public struct Employee {
    // 可变的实例变量
    var name: String
    // 不可变的实例变量
    let id: Int64

    // 静态变量
    private static var employeeCount: Int64 = 0

    // 静态构造函数,用于初始化静态成员
    static init() {
        employeeCount = 0
        println("静态构造函数被调用,初始化员工计数。")
    }

    // 构造函数
    public init(name: String, id: Int64) {
        this.name = name
        this.id = id
        employeeCount++
    }

    // 一个普通方法
    public func displayInfo() {
        println("员工ID: ${id}, 姓名: ${name}")
    }

    // 静态方法
    public static func getCount(): Int64 {
        return employeeCount
    }

    // 可变方法,可以修改 var 声明的实例变量
    public mut func changeName(newName: String) {
        this.name = newName
    }
}

2.struct 实例化

        仓颉的 struct 定义需遵循成员变量必须初始化原则,支持两种初始化方式:直接赋值 构造函数赋值,且结构体的构造函数分为【主构造函数】和【普通构造函数】,有明确的语法约束。

示例:User 结构体

package jk0909demo.chapter2

public struct User {

    //定义变量,有两种初始化机制,必须要赋值
    //1.直接赋值
    //2.通过构造函数赋值
    protected  var name: String
    protected  var phone: String

    // 主构造函数只能有一个
    public User(name: String, phone: String) {
        this.name = name
        this.phone = phone
        println("姓名为:${this.name},手机号码为:${this.phone}")
    }

    // 普通构造函数:用init关键字,支持无参/单参等不同参数列表
    public init() {
        this.name = "薄荷"
        this.phone = "123456789"
        println("姓名为:${this.name},手机号码为:${this.phone}")
    }

     // 重载普通构造函数:参数列表需与其他构造函数不同
    public init(name: String) {
        this.name = name
        this.phone = "13913321086"
        println("姓名为:${this.name},手机号码为:${this.phone}")
    }
}

代码解析

  1. 成员变量name/phone未直接赋值,因此必须通过构造函数完成初始化,否则编译报错
  2. 主构造函数(public User(...))是结构体的核心构造逻辑,仅能定义一个
  3. 普通构造函数(init)可重载,但需保证参数列表唯一(个数 / 类型不同)
  4. 构造函数内通过this关键字访问当前实例的成员变量
package jk0908demo

//导入包
import jk0908demo.chapter2.User

//仓颉是个多范式的语言,多种语法组成,轻量级
main() {  

   //创建Struct实例对象,变量名称: struct的名 = struct的名()
   //()依赖Struct提供的构造函数
   var  s1: User  = User()
   var  s2: User = User("茉莉1")
   var  s3: User = User("茉莉2","987654321")

}

运行结果:

3.构造函数的调用约束

        仓颉对struct 构造函数的相互调用有严格限制:主构造函数不能调用其他构造函数,普通构造函数可调用本结构体的其他构造函数
示例:Stu 结构体(构造函数调用规则)

package jk0909demo.chapter3

public  struct  Stu{

    var  a1 :Int64

    // 主构造函数:禁止调用this()访问其他构造函数
    public Stu(str:String)
    {
        // this(10) // 编译报错:主构造函数不能通过this()调用其他构造函数
        this.a1  = 100
    }

    // 普通构造函数1:单参初始化
    public init(a1:Int64)
    {
        this.a1 = a1
    }

    // 普通构造函数2:无参,可调用其他构造函数
    public init()
    {
        this(10)  // 普通构造函数中可以使用this()调用本结构体的其它构造函数
        this.a1 =200
        println("a1的值为:${a1}")
  
    }


}
package jk0908demo
//导入包
import jk0908demo.chapter3.Stu
main() {  
    var s:Stu =Stu()
}

运行结果:

4.静态成员变量与静态构造函数

struct 支持静态成员变量静态构造函数,静态成员属于结构体本身(而非实例),用于存储全局共享数据,静态构造函数专门初始化静态变量。

示例:Emp 结构体(静态成员演示)

package jk0909demo.chapter5

public struct  Emp{

   // 实例变量:需实例化结构体后才能访问
   public var name : String 

   // 静态变量:属于结构体,所有实例共享
   public static var count :Int64  

   
   // 静态构造函数:无参数,仅初始化静态变量,不能用this
   static init()
   {
      count = 200
   }

    // 实例构造函数:初始化实例变量
    public Emp()
    {
        this.name  = "张三"
    }
}

代码解析

  1. 静态变量count需通过static init()初始化,静态构造函数无参数不能使用 this 关键字、且不能被访问修饰符修饰函数体中必须完成对所有未初始化的静态成员变量的初始化,否则编译报错。
  2. 访问方式区分:
    • 实例变量let emp = Emp(); emp.name;【通过创建的实例名去访问】
    • 静态变量Emp.count【无需实例化,直接通过结构体名访问】
  3. 静态构造函数在结构体首次被使用时自动执行,且仅执行一次。
package jk0908demo
//导入包
import jk0908demo.chapter5.Emp
main() {  
   println("count的值为:${Emp.count}")
   var emp:Emp = Emp()
   println("name的值为:${emp.name}")
}

运行结果:

5.struct 的核心特性:值传递

        仓颉中 struct值类型,Class 是引用类型,最核心的区别体现在赋值 / 传参时的行为:struct 赋值会拷贝完整数据,Class 赋值仅传递内存引用。

示例:值传递 vs 引用传递对比

struct值传递

package jk0909demo.chapter6
public struct Employee{
    var name: String

    public Employee(){
        this.name = "QQ"
    }

    public init(name: String){
        this.name = name
    }

    public func execEmployee(){
        var emp1: Employee = Employee("福西西")
        println("现在的姓名为:${emp1.name}")   // 输出:福西西

        var emp2 = emp1     // 拷贝emp1的完整数据,emp2是新实例
        emp2.name = "阿信"

        println("现在的姓名为:${emp1.name}")   // 输出:福西西(emp1不受影响)
    }
   
}

【class引用传递

package jk0909demo.chapter6
public class Employee1{
    var name: String

    public Employee1(){
        this.name = "QQ"
    }

    public init(name: String){
        this.name = name
    }

    public func execEmployee1(){
        var emp1: Employee1 = Employee1("福西西")
        println("现在的姓名是${emp1.name}")   // 输出:福西西

        var emp2  = emp1   // 传递引用,emp2和emp1指向同一实例
        emp2.name = "阿信"

         println("现在的姓名是${emp1.name}")  // 输出:阿信(emp1被修改)

    }
}

值传递 vs 引用传递

类型 赋值行为 内存存储 修改影响
struct 拷贝完整数据,生成新实例 栈内存 新实例修改不影响原实例
class 传递引用,指向同一实例 堆内存 新引用修改会影响原实例

6.struct 的可变控制:mut 关键字与属性设计器

6.1 mut 关键字:修改实例变量的必要条件

        struct 的普通实例方法默认不能修改成员变量,必须添加mut关键字声明为【可变方法】,才能修改实例变量的值。

示例:mut 方法修改实例成员变量

package jk0909demo.chapter7
// 简化示例:mut方法的基础使用
public struct Emp1 {
    var count: Int64 = 0
    // 可变方法:加mut才能修改实例变量
    public mut func add() {
        this.count += 1
    }
}
public func execEmp1() {
    var emp1: Emp1 = Emp1()
    emp1.add()
    println("count的值为:${emp1.count}") // 输出:1
}

6.2 属性设计器

        仓颉不推荐使用 Java 风格的setXXX/getXXX方法封装成员变量,而是提供属性设计器(Prop),通过get/set实现成员变量的安全访问,同时强化封装性。

示例:Emp1 结构体(属性设计器)实践

package jk0909demo.chapter7

public struct Emp1{
    // 私有成员变量:禁止外部直接访问,强化封装
    private var count: Int64 = 200

    // 属性设计器
    public mut prop PropCount: Int64{  //注意这里没有()
        get(){
            this.count
        }
        set(newcount){
            this.count = newcount
        }
    }
}

public func execEmp1(){
    var emp1: Emp1 = Emp1()
    // emp1.count // 编译报错:private变量禁止直接访问,私有的目的是封装,封装的作用是加强访问的安全性
    println(emp1.PropCount)   // 调用get(),输出:200

    emp1.PropCount = 400      // 调用set(),修改count为400
    println(emp1.PropCount)   // 输出:400
}

代码解析

  1. 私有成员变量countprivate修饰,外部无法直接访问,保证数据安全
  2. 属性设计器PropCount是对外的访问入口,mut修饰表示支持写入操作
  3. get()方法负责返回成员变量值,set(newcount)方法负责接收外部传入的值并赋值给count
  4. 调用方式:读取emp1.PropCount等价于执行get(),赋值emp1.PropCount = 400等价于执行set(400)
package jk0909demo
// 导入包
import jk0909demo.chapter7.execEmp1
main(){
 execEmp1()
}

运行结果:

7.struct 综合实践

        以下整合前文所有知识点,实现一个包含【静态变量、随机数、属性设计器、构造函数】的完整 Struct 案例:

package jk0909demo.chapter8

import std.random.Random

public struct User{

    // 姓名  可变变量
    private var name: String

    // 随机数   不可变变量
    private let r1 = Random()

    // 用户数量  静态变量(全局共享)
    private static var cn: Int64

    // 静态构造函数,只能初始化静态变量,不能有this关键字
    static init(){
        cn = 0
     }

    // 主构造函数:初始化姓名,生成随机年龄,统计用户数量
      public User(name: String){
        this.name = name
        var age = this.r1.nextInt16(100)    // 生成0-99的随机整数
        cn++    // 静态变量自增,统计用户数
        println("用户的姓名为:${this.name},年龄为:${age},用户的数量为:${cn}")
      }

    // 属性设计器:封装name的读写
      public mut prop PropName: String{
        get(){
            this.name
        }
        set(newName){
            this.name = newName
        }
      }

}

public func execUser(){
    var u1: User =  User("QQ")
    var u2: User =  User("Jasmine")

    println(u1.PropName)
    println(u2.PropName)

    u1.PropName = "WW"
    println(u1.PropName)
    
}
package jk0909demo
// 导入包
import jk0909demo.chapter8.execUser
main(){
   execUser()
}

运行结果:

核心知识点总结

  • 构造函数规则:主构造函数仅一个,不能调用其他构造函数;普通构造函数可重载,且能调用同结构体的其他构造函数
  • 值类型特性:Struct 赋值时拷贝完整数据,与 Class 的引用传递形成核心区别
  • 可变控制:修改实例变量的方法需加mut关键字,保证数据修改的可控性
  • 封装特性:推荐使用属性设计器(Prop)替代 set/get 方法,结合private修饰符强化数据安全
  • 静态成员:静态变量 / 构造函数属于结构体本身,用于存储全局共享数据,静态构造函数仅初始化静态变量。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐