合约函数
在本节中,我们将了解合约中可能遇到的不同类型的函数:
1.构造器(Constructors)
构造函数是一种特殊类型的函数,只在部署合约时运行一次,可用于初始化合约的状态。
#[constructor]
fn constructor(ref self: ContractState, owner: Person) {
self.names.write(owner.address, owner.name);
self.total_names.write(1);
self.owner.write(owner);
}
一些需要注意的重要规则:
1.您的合约不能有一个以上的构造函数。
2.您的构造函数必须命名为 constructor
。
3.它必须使用 #[constructor]
属性标注。
2.公共函数
如前所述,公有函数可以从合约外部访问。它们必须定义在带有#[external(v0)]
属性注解的实现块中。这个属性只影响可见性(public 或 private/internal),但并不影响这些函数修改合约状态的能力。
#[external(v0)]
impl NameRegistry of super::INameRegistry<ContractState> {
fn store_name(ref self: ContractState, name: felt252, registration_type: RegistrationType) {
let caller = get_caller_address();
self._store_name(caller, name, registration_type);
}
fn get_name(self: @ContractState, address: ContractAddress) -> felt252 {
let name = self.names.read(address);
name
}
fn get_owner(self: @ContractState) -> Person {
let owner = self.owner.read();
owner
}
}
外部函数
外部函数是可以修改合约状态的函数。它们是公共的,可以被任何其他合约或外部调用。
外部函数是 public 函数,其中的 self:ContractState
以引用的形式通过关键字 ref
传递,使得你可以修改合约的状态。
fn store_name(ref self: ContractState, name: felt252, registration_type: RegistrationType) {
let caller = get_caller_address();
self._store_name(caller, name, registration_type);
}
视图函数
视图函数是只读函数,允许你访问合约中的数据,同时确保合约的状态不会被修改。它们可以被其他合约或外部调用。
视图函数是 public 函数,其中 self.ContractState
被作为快照传入,这会防止你修改合约的状态。
fn get_name(self: @ContractState, address: ContractAddress) -> felt252 {
let name = self.names.read(address);
name
}
注意: 外部函数和视图函数都是公共函数,这一点很重要。要在合约中创建内部函数,您需要在使用
#[external(v0)]
属性标注的实现块之外定义它。
3.私有函数
未在注有#[external(v0)]
属性的代码块中定义的函数是私有函数(也称为内部函数)。它们只能在合约内部调用。
#[generate_trait]
impl InternalFunctions of InternalFunctionsTrait {
fn _store_name(
ref self: ContractState,
user: ContractAddress,
name: felt252,
registration_type: RegistrationType
) {
let mut total_names = self.total_names.read();
self.names.write(user, name);
self.registration_type.write(user, registration_type);
self.total_names.write(total_names + 1);
self.emit(StoredName { user: user, name: name });
}
}
等等,这个
#[generate_trait]
属性是什么?这个实现的trait定义在哪里?嗯,#[generate_trait]
属性是一个特殊的属性,它告诉编译器为实现块生成一个trait定义。这允许你摆脱为实现块定义trait和实现trait的模板代码。我们将在下一节中看到更多关于这方面的内容。
说到这里,您可能还在想,如果您不需要在您的函数(例如,辅助函数/库函数)中访问合约的状态,所有这些是否真的有必要。事实上,您也可以在实现块之外定义内部函数。我们 需要 在实现块内部定义函数的唯一原因是我们想要访问合约的状态。
fn get_contract_name() -> felt252 {
'Name Registry'
}
fn get_owner_storage_address(self: @ContractState) -> starknet::StorageBaseAddress {
self.owner.address()
}