Tổng quan
Trong ngôn ngữ lập trình Cadence Flow, struct (còn được gọi là “structure”) là một kiểu dữ liệu tùy chỉnh được định nghĩa bởi người dùng. Cấu trúc (structure) cho phép tổ chức các biến khác nhau với các kiểu dữ liệu khác nhau trong cùng một vùng nhớ để tạo thành một đối tượng lớn hơn, phức tạp hơn, có thể dễ dàng truy cập và quản lý.
Struct đặc biệt hữu ích trong việc lưu trữ nhiều giá trị có cấu trúc tương tự với nhau. Trong một struct, các giá trị được gọi là thành phần và mỗi thành phần có một tên và một giá trị. Structs là cấu trúc dữ liệu phức tạp cho phép bạn chứa nhiều giá trị liên quan trong một đối tượng duy nhất.
Ví dụ, bạn có thể tạo một struct cho một nhân viên có tên, số điện thoại và địa chỉ. Mỗi nhân viên sẽ có một giá trị cho từng thành phần của struct, và bạn có thể lưu trữ nhiều nhân viên trong một mảng các struct. Cú pháp tạo một struct sẽ khác nhau tùy theo ngôn ngữ lập trình, nhưng chúng ta thường xác định tên cho struct và các thành phần của nó, sau đó tạo một biến mới với kiểu dữ liệu là struct đó.
Mỗi struct trong Cadence Flow bao gồm một tập hợp các biến, mỗi biến được định nghĩa bởi tên, kiểu dữ liệu và giá trị khởi tạo. Cú pháp để định nghĩa một struct trong Cadence Flow như sau:
struct [tên_struct] {
[kiểu_dữ_liệu_1] [tên_biến_1] = [giá_trị_1];
[kiểu_dữ_liệu_2] [tên_biến_2] = [giá_trị_2];
...
[kiểu_dữ_liệu_n] [tên_biến_n] = [giá_trị_n];
};
Trong đó, [tên_struct]
là tên của cấu trúc, [kiểu_dữ_liệu_i]
là kiểu dữ liệu của biến thứ i, [tên_biến_i]
là tên của biến thứ i, và [giá_trị_i]
là giá trị khởi tạo của biến thứ i (nếu có).
Việc sử dụng struct trong Cadence Flow giúp cho việc quản lý dữ liệu trở nên dễ dàng hơn, đặc biệt là trong các chương trình lớn và phức tạp.
Series hướng dẫn lập trình Cadence
Struct (Cấu trúc)
Dưới đây là ví dục Struct trên ngôn ngữ Cadence
pub struct Profile { pub let firstName: String pub let lastName: String pub let birthday: String pub let account: Address // `init()` bắt đầu gọi khi Struct được tạo ra... // Bạn sẽ phải truyền 4 điều kiện khi tạo struct init(_firstName: String, _lastName: String, _birthday: String, _account: Address) { self.firstName = _firstName self.lastName = _lastName self.birthday = _birthday self.account = _account } }
Về cơ bản, chúng ta đã xác định một Loại (Type) mới có tên Profile. Nó là một cấu trúc. Như bạn có thể thấy, nó chứa 4 loại dữ liệu:
- Tên (
firstName
) - Họ (
lastName
) - Ngày sinh (
birthday
) - Địa chỉ address (
account
)
Việc tạo một Struct thực sự hữu ích khi chúng ta muốn thông tin được tập hợp lại với nhau trong một nơi.
Hãy suy nghĩ về lý do tại sao điều này là hữu ích. Giả sử chúng ta tạo một tập lệnh mới trong Flow playground và chúng ta muốn trả lại thông tin hồ sơ của ai đó. Chúng ta nên làm việc đó như thế nào? Nếu không có Struct, chúng ta sẽ phải trả về một mảng Chuỗi (String
) chứa tất cả thông tin, chuyển đổi account
thành String
, v.v. Đó là rất nhiều nỗ lực và khó khăn. Thay vào đó, chúng tôi chỉ có thể trả về cấu trúc Hồ sơ. Hãy đi đến một ví dụ thực tế.
Cũng lưu ý rằng Structs có hàm init()
được gọi khi Struct được tạo, giống như hàm init()
được gọi khi hợp đồng được triển khai. Ngoài ra, bạn sẽ nhận thấy tôi có xu hướng sử dụng “_” trước tên biến của mình trong các hàm init()
. Đây chỉ là điều tôi làm để phân biệt giữa biến thực tế và giá trị khởi tạo. Điều này KHÔNG giống với cú pháp nhãn đối số ẩn _
.
Ví dụ thực tế
Hãy bắt đầu bằng cách triển khai Hợp đồng thông minh mới cho tài khoản 0x01
:
pub contract Authentication { pub var profiles: {Address: Profile} pub struct Profile { pub let firstName: String pub let lastName: String pub let birthday: String pub let account: Address init(_firstName: String, _lastName: String, _birthday: String, _account: Address) { self.firstName = _firstName self.lastName = _lastName self.birthday = _birthday self.account = _account } } pub fun addProfile(firstName: String, lastName: String, birthday: String, account: Address) { let newProfile = Profile(_firstName: firstName, _lastName: lastName, _birthday: birthday, _account: account) self.profiles[account] = newProfile } init() { self.profiles = {} } }
- Chúng ta đã xác định một hợp đồng mới có tên
Authentication
- Chúng ta đã xác định một từ điển có tên
profiles
vơiAddress
map với loại làProfile
- Chúng ta đã xác định một Struct mới có tên là
Profile
chứa 4 trường - Chúng ta đã định nghĩa một hàm mới có tên
addProfile
nhận 4 tham số và tạoProfile
mới. Sau đó, nó tạo một mapping mới từaccount
->Profile
được liên kết với tài khoản đó - Khởi tạo
profiles
thành một từ điển trống khi hợp đồng được triển khai
Tạo Profile mới
Bây giờ chúng ta đã xác định một Cấu trúc mới, hãy xem tại sao nó có thể hữu ích.
import Authentication from 0x01 transaction() { prepare(signer: AuthAccount) {} execute { log("We're done.") } }
Bây giờ, chúng ta muốn tạo một hồ sơ mới vào profiles
trong hợp đồng Authentication. Làm thế nào chúng ta có thể làm điều này? Hãy gọi hàm addProfile
với tất cả các đối số mà chúng ta cần như sau: Authentication.addProfile(firstName: firstName, lastName: lastName, birthday: birthday, account: account)
. Nhưng chờ đã, trước tiên chúng ta cần lấy những đối số này từ đâu đó! Chúng ta có thể làm điều đó bằng cách chuyển chúng vào giao dịch dưới dạng đối số, như sau:
import Authentication from 0x01 transaction(firstName: String, lastName: String, birthday: String, account: Address) { prepare(signer: AuthAccount) {} execute { Authentication.addProfile(firstName: firstName, lastName: lastName, birthday: birthday, account: account) log("We're done.") } }
Cách đọc Profile
Để đọc Profile mới, hãy mở một Script, sao chép và dán mã tập lệnh soạn sẵn:
import Authentication from 0x01 pub fun main() { }
Bây giờ, hãy thử đọc Profile. Chúng ta có thể làm điều này bằng cách chuyển vào một Địa chỉ đại diện cho một tài khoản, vì chúng ta đã Mapping các Account -> Profile trong từ điển hồ sơ của chúng ta trong hợp đồng. Sau đó, chúng ta có thể trả lại loại Hồ sơ mà chúng tôi nhận được từ từ điển đó, như vậy:
import Authentication from 0x01 pub fun main(account: Address): Authentication.Profile { return Authentication.profiles[account]! }
Cũng lưu ý kiểu trả về ở đây: Authentication.Profile
. Đó là bởi vì chúng tôi đang trả lại một loại Profile
được xác định trong hợp đồng Authentication
. Các loại luôn dựa trên hợp đồng mà chúng được xác định. Và bùm! Đó là nó. Bây giờ, bất cứ ai gọi tập lệnh này đều có thể có tất cả thông tin hồ sơ họ cần.