為自己Coding
為自己Coding

YO~~ 剛跨入AI人工智慧領域的小小工程師, 熱愛自學, 熱愛分享, 下班後的我想為自己Coding, 積極撰寫教學文, 想將自學的程式知識分享給大家, 不斷追求進步的自己, 希望有一天能回饋社會,幫助需要幫助的人, 如果您有什麼很酷的想法,也覺得我還行,歡迎您找我合作~~ IG: https://www.instagram.com/coding_4_me/

[Aptos學習筆記#3]Move進階使用 - 結構Struct用法

這篇記錄Move中的結構如何使創建與使用


攝影師:Pixabay: https://www.pexels.com/zh-tw/photo/355465/


目錄

  • 結構體
  • 如何定義結構體
  • 遞歸結構體 Recursive Definition
  • 訪問結構體字段
  • 回收結構體 Destructing Structures
  • 為結構體實現Getter函數 Implementing getter functions for struct fields


一. 結構體

  • 為一個自定義類型,可以具有複雜數據,也可以不具有任何數據
  • 由鍵值組成,可以想成使用類似於Python的Dict由”key-value”儲存
  • key為屬性的名稱,value則為儲存的內容
  • 使用struct關鍵字定義
  • 結構體最多可以擁有4個能力
  • 為Move創建自定義類型的唯一方法

二. 定義

  • 結構體只能在模塊中進行定義,且以struct當關鍵字開頭
  • 一個結構體最多可以擁有65535的字段
  • 可以使用新定義出的類型,當另一個結構體的字段類型
struct Name {
    FIELD1: TYPE1,
    FILED2: TYPE2,
    FILED3: TYPE3,
    ...
}
  • 例子
module M {
    
    struct Empty {}

    struct NewStruct {
        field1: address,
        field2: Empty,
        field3: u64
    }

    struct Human {
        field1: u8,
        field2: bool,
        field3: address,
        field4: bool,
        field5: u64,
				
        field6: NewStruct  // 可以使用新定義出的類型,當另一個結構體的字段類型
    }

}
  • 透過定義這個結構體的模塊來訪問新自定義的類型
M::NewStruct;
// or
M::Human


三. 遞歸結構體 Recursive definition

  • Move可以使用其他結構體當作成員,但不能遞歸使用自己本身的結構體
  • 例子: 在相同結構體中遞歸使用本身的結構體當類型,是不被允許的
module M {
    struct SameStruct {
    
        field1: SameStruct
    }
}

創建結構體的

  • 使用結構體的定義來創建該實例,只是傳入的是值不是類型
  • 例子: 創建一個student的實例
module Human {
    
    struct Student {
        student_id: u8,
        age: u64
    }

    public fun new_student(s_id: u8, s_age: u64): Student {
        let student = Student {
            student_id: s_id,
            age: s_age
        };

        student    
    }
}
  • 簡化創建的程式碼 - 透過傳遞與結構體的字段名稱香匹配的變量名稱
  • 例子: new_student()使用了簡化的方法
module Human {
    
    struct Student {
        student_id: u8,
        age: u64
    }

    public fun new_student(student_id: u8, age: u64): Student {
        Student {
            student_id,
            age
        }
    }

    // 另一種寫法: Student { student_id, age }
}
  • 創建一個空的結構體(沒有字段),僅需使用花括號
module Example {
    struct Empty {}

    public fun empty(): Empty {
        Empty {}
    }
}


四. 訪問結構體字段

  • 只有模塊(Module)可以訪問自己的字段(fields),在模塊(Module)外部字段(fields)是屬於private,沒辦法被訪問
  • 結構的字段只有在模塊內可見,在此模塊外(腳本或是其他模塊中),它只是一種類型
  • 可以透過.符號來訪問結構的字段(fields) ex. <struct>.<property>
public fun get_student_age(student: Student): u64 {
    student.age
}
  • 若在同一個模塊中定義嵌套結構類型(Nested Struct Type),可以使用類似的方法進行訪問<>
<struct>.<field>
<struct>.<field>.<nested_struct_field>


五. 回收結構體 Destructing Structures

  • 使用語法 let <STRUCT DEF> = <STRUCT> 銷毀或解構一個結構
module Human {
    
    struct Student {
        student_id: u8,
        age: u64
    }

    public fun destroy(student: Student) {
        
        // 變數必須匹配結構
        // 必須指定所有結構
        let Student { student_id, age } = student;    
    
        // 當銷毀student被丟棄後
        // 它的字段現在是變數,可以被使用
        (student_id, age)
    }
}
  • 在Move中禁止使用未使用到的變數,有時候可能需要在不使用其字段的情形下銷毀結構,對於未使用到的結構字段使用_表示
module Human {
    
    struct Student {
        student_id: u8,
        age: u64
    }

    public fun destroy(student: Student) {
        
        // 這樣銷毀結構,就不會產生未使用到的變數 
        let Student {student_id: _, age: _ } = student;

        // 或是只留student_id,然後不要產生age變數
        // let Student {student_id, age: _ } = student;    
    }
}
  • 銷毀結構體現在看起來並沒有那麼重要,但在Resource中會扮演相當重要的角色


六. 為結構體實現 getter 函數 - Implementing getter-functions for struct fields

  • 目的是讓結構體在外部(Module 以外)可以被讀取,所以需要使用一些方法
  • 這些方法會讀取struct中的字段(fields)並將它們當作回傳值傳遞
  • getter 方法的調用方式與結構體訪問字段的方法相同,但如果我們的模塊(Module)定義了多個結構體,那getter方法就可能會帶來不便
  • 例子: 我們創建一個Student結構體,然後撰寫兩個getter方法來獲取裡面的字段
module Human {

    struct Student {
        student_id: u8,
        age: u64
    }

    public fun new_student(student_id: u8, age: 64): Student {
        Student {student_id, age}
    }

    // 讓外部訪問student_id的方法
    public fun student_id(student: &Student): u8 {
        student.student_id
    }

    // 讓外部訪問age的方法
    public fun age(student: &Student): u64 {
        student.age
    }

    // ... fun destroy ...
}
  • 透過getter的方法,在Script中訪問模塊(Module)中的結構體字段(fields)
script {
    use {{sender}}::Human as H;
    use 0x1::Debug;

    fun main() {
        // 使用Module中創建Student結構的方法
        let student = H::new_student(1, 26);

        // 印出Student ID
        Debug::print<u8>(&H::student_id(&student)) 

        // 印出Age
        Debug::print<u8>(&H::age(&student))
    
        // 無法使用下邊這種直接訪問結構字段的寫法
        // let student_id = student.student_id;
        // let age = student.age;
    }
}


Reference

The Move Language - The Move Book

CC BY-NC-ND 2.0 版权声明

喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。

加载中…

发布评论