本文介绍了 Solidity 中合约类型的概念,合约本身也是一种数据类型。主要讲解了如何使用 new 关键字创建合约,以及如何与已部署的合约进行交互,包括合约类型与地址类型之间的转换,这对于构建复杂的 DApp 至关重要。
在前面的章节中,我们学习了 Solidity 的基本数据类型(整型、布尔、地址等)。实际上,合约本身也是一种数据类型,称为合约类型。理解合约类型对于合约间的交互至关重要。
本章你将学到:
new 关键字创建合约每一个合约,合约本身就是一个数据类型,称为合约类型。如下代码定义了一个 Hello 合约类型:
pragma solidity ^0.8.0;
contract Hello {
function sayHi() public pure returns (uint) {
return 10;
}
}
就像我们可以声明 uint x 或 address addr 一样,我们也可以声明 Hello h 来表示一个 Hello 合约类型的变量。
我们要如何使用合约类型呢?主要有两种方式:
new 关键字部署一个新合约我们可以通过合约类型创建出一个合约实例(即部署一个合约)。这里是一个例子:
pragma solidity ^0.8.0;
contract Hello {
function sayHi() public pure returns (uint) {
return 10;
}
}
contract HelloCreator {
uint public x;
Hello public h;
function createHello() public returns (address) {
// 使用 new 关键字创建合约
h = new Hello();
return address(h);
}
}
上面的代码,调用 HelloCreator 合约的 createHello 函数可以创建一个合约(new Hello())。
我们在 Remix 演练一下,先部署 HelloCreator 合约(注意不是部署 Hello):

然后调用 createHello 在链上创建一个 Hello 合约:

右下角的日志中,可以看到创建的合约地址 0x93Ff8fe9BF4005...。让我们在 Remix 加载该合约,并调用 sayHi 来验证该合约确实部署成功了。
在 Remix 使用 Hello 的地址加载 Hello, 选择 Hello 合约, 在 At Address 处填入合约地址,如图:

然后调用 sayHi() :

createHello 函数中,创建的合约赋值给了状态变量 h, 在 HelloCreator 合约中,也可以利用 h 来调用 sayHi 函数。例如,可以在 HelloCreator 合约中,添加如下函数:
function callHi() public returns (uint) {
// 通过合约类型变量调用函数
x = h.sayHi();
return x;
}
这展示了合约间交互的基本模式:一个合约可以调用另一个合约的公开函数。
合约类型可以与地址类型相互转换:
contract TypeConversion {
Hello public hello;
function createAndConvert() public {
hello = new Hello();
// 合约类型转换为地址
address helloAddr = address(hello);
// 地址转换为合约类型
Hello h2 = Hello(helloAddr);
}
}
这种转换在合约间交互时非常常见。
本节我们学习了合约类型的概念和使用:
new 关键字可以在合约中部署新的合约理解合约类型是掌握 Solidity 合约间交互的基础,这在构建复杂的 DApp 时非常重要。
尝试完成以下练习:
pragma solidity ^0.8.0;
// TODO: 定义一个 Counter 合约,包含:
// - 一个 count 状态变量
// - increment() 函数增加计数
// - getCount() 函数返回当前计数
// TODO: 定义一个 CounterFactory 合约,包含:
// - createCounter() 函数创建新的 Counter
// - incrementCounter() 函数调用创建的 Counter 的 increment
// - getCounterValue() 函数获取 Counter 的当前值
想了解更多关于合约创建的知识,可以参考:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!