仓颉编程语言:定义 struct 类型

仓颉编程语言中 struct 类型的定义

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

struct Rectangle {
    let width: Int64
    let height: Int64

    public init(width: Int64, height: Int64) {
        this.width = width
        this.height = height
    }

    public func area() {
        width * height
    }
}

上例中定义了名为 Rectangle 的 struct 类型,它有两个 Int64 类型的成员变量 width 和 height,一个有两个 Int64 类型参数的构造函数(使用关键字 init 定义,函数体中通常是对成员变量的初始化),以及一个成员函数 area(返回 width 和 height 的乘积)。

注意

struct 只能定义在源文件顶层。

struct 成员变量

struct 成员变量分为实例成员变量和静态成员变量(使用 static 修饰符修饰,且必须有初值),二者的区别在于实例成员变量只能通过 struct 实例(我们说 a 是 T 类型的实例,指的是 a 是一个 T 类型的值)访问,静态成员变量只能通过 struct 类型名访问。

实例成员变量定义时可以不设置初值(但必须标注类型,如上例中的 width 和 height),也可以设置初值,例如:

struct Rectangle {
    let width = 10
    let height = 20
}

struct 静态初始化器

struct 支持定义静态初始化器,并在静态初始化器中通过赋值表达式来对静态成员变量进行初始化。

静态初始化器以关键字组合 static init 开头,后跟无参参数列表和函数体,且不能被访问修饰符修饰。函数体中必须完成对所有未初始化的静态成员变量的初始化,否则编译报错。

struct Rectangle {
    static let degree: Int64
    static init() {
        degree = 180
    }
}

一个 struct 中最多允许定义一个静态初始化器,否则报重定义错误。

struct Rectangle {
    static let degree: Int64
    static init() {
        degree = 180
    }
    static init() { // Error, redefinition with the previous static init function
        degree = 180
    }
}

struct 构造函数

struct 支持两类构造函数:普通构造函数和主构造函数。

普通构造函数以关键字 init 开头,后跟参数列表和函数体,函数体中必须完成对所有未初始化的实例成员变量的初始化(如果参数名和成员变量名无法区分,可以在成员变量前使用 this 加以区分,this 表示 struct 的当前实例),否则编译报错。

struct Rectangle {
    let width: Int64
    let height: Int64

    public init(width: Int64, height: Int64) { // Error, 'height' is not initialized in the constructor
        this.width = width
    }
}

一个 struct 中可以定义多个普通构造函数,但它们必须构成重载(参见函数重载),否则报重定义错误。

struct Rectangle {
    let width: Int64
    let height: Int64

    public init(width: Int64) {
        this.width = width
        this.height = width
    }

    public init(width: Int64, height: Int64) { // Ok: overloading with the first init function
        this.width = width
        this.height = height
    }

    public init(height: Int64) { // Error, redefinition with the first init function
        this.width = height
        this.height = height
    }
}

除了可以定义若干普通的以 init 为名字的构造函数外,struct 内还可以定义(最多)一个主构造函数。主构造函数的名字和 struct 类型名相同,它的参数列表中可以有两种形式的形参:普通形参和成员变量形参(需要在参数名前加上 let 或 var),成员变量形参同时扮演定义成员变量和构造函数参数的功能。

使用主构造函数通常可以简化 struct 的定义,例如,上述包含一个 init 构造函数的 Rectangle 可以简化为如下定义:

struct Rectangle {
    public Rectangle(let width: Int64, let height: Int64) {}
}

主构造函数的参数列表中也可以定义普通形参,例如:

struct Rectangle {
    public Rectangle(name: String, let width: Int64, let height: Int64) {}
}

如果 struct 定义中不存在自定义构造函数(包括主构造函数),并且所有实例成员变量都有初始值,则会自动为其生成一个无参构造函数(调用此无参构造函数会创建一个所有实例成员变量的值均等于其初值的对象);否则,不会自动生成此无参构造函数。例如,对于如下 struct 定义,注释中给出了自动生成的无参构造函数:

struct Rectangle {
    let width: Int64 = 10
    let height: Int64 = 10
    /* Auto-generated memberwise constructor:
    public init() {
    }
    */
}

struct 成员函数

struct 成员函数分为实例成员函数和静态成员函数(使用 static 修饰符修饰),二者的区别在于:实例成员函数只能通过 struct 实例访问,静态成员函数只能通过 struct 类型名访问;静态成员函数中不能访问实例成员变量,也不能调用实例成员函数,但在实例成员函数中可以访问静态成员变量以及静态成员函数。

下例中,area 是实例成员函数,typeName 是静态成员函数。

struct Rectangle {
    let width: Int64 = 10
    let height: Int64 = 20

    public func area() {
        this.width * this.height
    }

    public static func typeName(): String {
        "Rectangle"
    }
}

实例成员函数中可以通过 this 访问实例成员变量,例如:

struct Rectangle {
    let width: Int64 = 1
    let height: Int64 = 1

    public func area() {
        this.width * this.height
    }
}

struct 成员的访问修饰符

struct 的成员(包括成员变量、成员属性、构造函数、成员函数、操作符函数(详见操作符重载章节))用 4 种访问修饰符修饰:private、internal、protected 和 public,缺省的含义是 internal。

  • private 表示在 struct 定义内可见。
  • internal 表示仅当前包及子包(包括子包的子包,详见章节)内可见。
  • protected 表示当前模块(详见章节)可见。
  • public 表示模块内外均可见。

下面的例子中,width 是 public 修饰的成员,在类外可以访问,height 是缺省访问修饰符的成员,仅在当前包及子包可见,其他包无法访问。

package a
public struct Rectangle {
    public var width: Int64
    var height: Int64
    private var area: Int64
    ...
}

func samePkgFunc() {
    var r = Rectangle(10, 20)
    r.width = 8               // Ok: public 'width' can be accessed here
    r.height = 24             // Ok: 'height' has no modifier and can be accessed here
    r.area = 30               // Error, private 'area' can't be accessed here
}
package b
import a.*
main() {
    var r = Rectangle(10, 20)
    r.width = 8               // Ok: public 'width' can be accessed here
    r.height = 24             // Error, no modifier 'height' can't be accessed here
    r.area = 30               // Error, private 'area' can't be accessed here
}

禁止递归 struct

递归和互递归定义的 struct 均是非法的。例如:

struct R1 { // Error, 'R1' recursively references itself
    let other: R1
}
struct R2 { // Error, 'R2' and 'R3' are mutually recursive
    let other: R3
}
struct R3 { // Error, 'R2' and 'R3' are mutually recursive
    let other: R2
}

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing ,不定期分享原创知识。

<think>好的,用户想了解如何在仓颉编程语言中实现链表数据结构,并且希望有一个定义示例。同时,他们还想测试对仓颉语言的支持程度。首先,我需要确认仓颉编程语言的语法和特性,是否支持结构体或类,以及指针或引用的使用方式。假设仓颉语言类似C或Go,可能使用结构体和指针来实现链表节点。 接下来,链表的定义通常包括节点结构,包含数据域和指向下一个节点的指针。比如,定义一个Node结构体,包含value和next字段。然后,可能需要创建几个节点,并连接它们形成链表。例如,node1 -> node2 -> node3 -> null。 然后,遍历链表并打印每个节点的值,以验证链表的正确性。这需要循环或递归访问每个节点,直到next为null。 用户可能还关心仓颉语言是否支持动态内存分配,比如是否有new或类似的函数来创建节点实例。此外,错误处理机制,比如空指针的处理,也是需要注意的地方。 考虑到用户提供的引用内容,虽然引用[1]和[2]似乎与链表无关,但可能需要忽略这些,专注于语言本身的特性。需要确保示例代码符合仓颉的语法,比如变量声明、函数定义、循环结构等。 最后,生成相关问题,可能涉及链表的操作(插入、删除)、性能分析、优化方法,以及仓颉语言的其他数据结构支持情况。确保问题与用户的需求相关,帮助他们进一步学习和测试仓颉语言的能力。</think>### 仓颉编程语言实现链表 在仓颉编程语言中,可以通过结构体和指针实现单向链表。以下示例代码展示了链表节点的定义与基本操作: ```cangjie // 定义链表节点结构体 struct ListNode { int value; ListNode* next; } // 创建链表节点函数 func create_node(int val) -> ListNode* { ListNode* node = alloc(sizeof(ListNode)) node.value = val node.next = null return node } // 链表遍历示例 func print_list(ListNode* head) { ListNode* current = head while current != null { io.print(current.value + " -> ") current = current.next } io.println("null") } // 主函数测试 func main() { // 创建三个节点 ListNode* node1 = create_node(10) ListNode* node2 = create_node(20) ListNode* node3 = create_node(30) // 连接节点形成链表 node1.next = node2 node2.next = node3 // 输出链表内容 print_list(node1) // 10 -> 20 -> 30 -> null } ``` ### 关键特性验证 1. **结构体支持**:通过`struct`关键字定义复合数据结构 2. **指针操作**:使用`*`声明指针类型,`alloc`进行内存分配[^2] 3. **函数定义**:`func`关键字声明函数,支持返回值类型标注 4. **控制结构**:`while`循环实现链表遍历 5. **内存管理**:需要手动分配内存(示例未展示释放操作)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值