19.Solidity源文件导入
Solidity支持利用import关键字将一个源文件中的合约导入到其他源文件中,以便让开发更加模块化。
19.1.源文件导入
源文件导入有两种方法:导入源文件中的全部合约和导入源文件中的部分合约。
- 方法一:导入源文件中的全部合约
import "filename"
相关字段 |
描述 |
import |
导入源文件的关键字 |
filename |
源文件路径 |
下面是名为ForwardCalulate.sol源文件
// 加法计算合约
contract Add{
// 加法计算函数
function add(int _num1, int _num2) public pure returns(int){
return _num1 + _num2;
}
}
// 减法计算合约
contract Subtract{
// 减法计算函数
function subtract(int _num1, int _num2) public pure returns(int){
return _num1 - _num2;
}
}
// 乘法计算合约
contract Multiply{
// 乘法计算函数
function multiply(int _num1, int _num2) public pure returns(int){
return _num1 * _num2;
}
}
// 除法计算合约
contract Divide{
// 除法计算函数
function divide(int _num1, int _num2) public pure returns(int){
return _num1 / _num2;
}
}
下面是名为AllImport.sol源文件
// 将ForwardCalculate.sol源文件中的全部导入
import "./ForwardCalculate.sol";
contract AllImport{
int num1 = 0;
int num2 = 0;
// 给num1状态变量赋值
function inputNum1(int _num1) public{
num1 = _num1;
}
// 给num2状态变量赋值
function inputNum2(int _num2) public{
num2 = _num2;
}
// 创建Add合约,并调用add()函数
function callAdd() public returns(int){
Add add = new Add();
return add.add(num1, num2);
}
// 创建Subtract合约,并调用subtract()函数
function callSubtract() public returns(int){
Subtract subtract = new Subtract();
return subtract.subtract(num1, num2);
}
// 创建Multiply合约,并调用multiply()函数
function callMultiply() public returns(int){
Multiply multiply = new Multiply();
return multiply.multiply(num1, num2);
}
// 创建Divide合约,并调用Divide()函数
function callDivide() public returns(int){
Divide divide = new Divide();
return divide.divide(num1, num2);
}
}
- 方法二:导入源文件中的部分合约
import { ContactName1, ContractName2... } from "filename"
相关字段 |
描述 |
import |
导入源文件的关键字 |
ContactName1, ContactName2... | 想要导入的合约名称 |
from | 导入源文件的关键字 |
filename |
源文件路径 |
下面是名为PartImport.sol源文件
// 只将ForwardCalculate.sol源文件中的Subtract和Divide合约导入
import {Subtract, Divide} from "./ForwardCalculate.sol";
contract PartImport{
int num1 = 0;
int num2 = 0;
// 给num1状态变量赋值
function inputNum1(int _num1) public{
num1 = _num1;
}
// 给num2状态变量赋值
function inputNum2(int _num2) public{
num2 = _num2;
}
// 创建Subtract合约,并调用subtract()函数
function callSubtract() public returns(int){
Subtract subtract = new Subtract();
return subtract.subtract(num1, num2);
}
// 创建Divide合约,并调用Divide()函数
function callDivide() public returns(int){
Divide divide = new Divide();
return divide.divide(num1, num2);
}
}
19.2.取别名
在同一个源文件中,合约名称不可重复,有可能在导入文件后,造成合约名称重复。有两种解决方案:给源文件取别名或给源文件中的合约取别名。
- 方案一:给源文件取别名
在采用“导入源文件中的全部合约”方法时,给源文件取个别名,然后通过“别名.合约名”的方式调用合约。
import "filename" as fileAlias
相关字段 |
描述 |
import |
导入源文件的关键字 |
filename |
源文件路径 |
as | 取别名的关键字 |
fileAlias | 给源文件自定义的别名 |
下面是名为ReverseCalculate.sol源文件
// 加法计算合约
contract Add{
// 加法计算函数
function add(int _num1, int _num2) public pure returns(int){
return _num2 + _num1;
}
}
// 减法计算合约
contract Subtract{
// 减法计算函数
function subtract(int _num1, int _num2) public pure returns(int){
return _num2 - _num1;
}
}
// 乘法计算合约
contract Multiply{
// 乘法计算函数
function multiply(int _num1, int _num2) public pure returns(int){
return _num2 * _num1;
}
}
// 除法计算合约
contract Divide{
// 除法计算函数
function divide(int _num1, int _num2) public pure returns(int){
return _num2 / _num1;
}
}
下面是名为AllImport_Alias.sol源文件
// 将ForwardCalculate.sol源文件中的合约全部导入,并给源文件取别名为ForwardAlias
import "./ForwardCalculate.sol" as ForwardAlias;
// 将ReverseCalculate.sol源文件中的合约全部导入,并给源文件取别名为ReverseAlias
import "./ReverseCalculate.sol" as ReverseAlias;
contract AllImport_Alias{
int num1 = 0;
int num2 = 0;
// 给num1状态变量赋值
function inputNum1(int _num1) public{
num1 = _num1;
}
// 给num2状态变量赋值
function inputNum2(int _num2) public{
num2 = _num2;
}
// 创建Add合约,并调用add()函数
function callAdd() public returns(int, int){
ForwardAlias.Add forwardAdd = new ForwardAlias.Add();
ReverseAlias.Add reverseAdd = new ReverseAlias.Add();
return (forwardAdd.add(num1, num2), reverseAdd.add(num1, num2));
}
// 创建Subtract合约,并调用subtract()函数
function callSubtract() public returns(int, int){
ForwardAlias.Subtract forwardSubtract = new ForwardAlias.Subtract();
ReverseAlias.Subtract reverseSubtract = new ReverseAlias.Subtract();
return (forwardSubtract.subtract(num1, num2), reverseSubtract.subtract(num1, num2));
}
// 创建Multiply合约,并调用multiplay()函数
function callMultiply() public returns(int, int){
ForwardAlias.Multiply forwardMultiply = new ForwardAlias.Multiply();
ReverseAlias.Multiply reverseMultiply = new ReverseAlias.Multiply();
return (forwardMultiply.multiply(num1, num2), reverseMultiply.multiply(num1, num2));
}
// 创建Divide合约,并调用divide()函数
function callDivide() public returns(int, int){
ForwardAlias.Divide forwardDivide = new ForwardAlias.Divide();
ReverseAlias.Divide reverseDivide = new ReverseAlias.Divide();
return (forwardDivide.divide(num1, num2), reverseDivide.divide(num1, num2));
}
}
- 方案二:给源文件中的合约取别名
在采用“导入源文件中的部分合约”方法时,给合约取个别名,然后直接使用别名调用合约。
import { contractName1 as contractAlias1, contractName2 as contractAlias2... } from "filename"
相关字段 |
描述 |
import |
导入源文件的关键字 |
ContactName1、ContactName2 | 想要导入的合约名称 |
as | 取别名的关键字 |
contractAlias1、contractAlias2 |
给合约自定义的别名 |
from | 导入源文件的关键字 |
filename |
源文件路径 |
下面是名为PartImport_Alias.sol源文件
// 只将ForwardCalculate.sol源文件中的Subtract和Divide合约导入
// 并给这两个合约分别取别名为ForwardSubtract和ForwardDivide
import {Subtract as ForwardSubtract, Divide as ForwardDivide} from "./ForwardCalculate.sol";
// 只将ReverseCalculate.sol源文件中的Subtract和Divide合约导入
// 并给这两个合约分别取别名为ReverseSubtract和ReverseDivide
import {Subtract as ReverseSubtract, Divide as ReverseDivide} from "./ReverseCalculate.sol";
contract PartImport_Alias{
int num1 = 0;
int num2 = 0;
// 给num1状态变量赋值
function inputNum1(int _num1) public{
num1 = _num1;
}
// 给num2状态变量赋值
function inputNum2(int _num2) public{
num2 = _num2;
}
// 创建Subtract合约,并调用subtract()函数
function callSubtract() public returns(int, int){
ForwardSubtract forwardSubtract = new ForwardSubtract();
ReverseSubtract reverseSubtract = new ReverseSubtract();
return (forwardSubtract.subtract(num1, num2), reverseSubtract.subtract(num1, num2));
}
// 创建Divide合约,并调用divide()函数
function callDivide() public returns(int, int){
ForwardDivide forwardDivide = new ForwardDivide();
ReverseDivide reverseDivide = new ReverseDivide();
return (forwardDivide.divide(num1, num2), reverseDivide.divide(num1, num2));
}
}
20.Solidity全局属性
Solidity语言预设了一些特殊的变量和函数,他们主要用来提供关于区块链的信息或一些通用的工具函数,这些变量和函数都是全局的,被称为全局变量和全局函数。
20.1.数字函数
- addmod(uint x, uint y, uint k) returns(uint)
等同(x + y) % k。
- mulmod(uint x, uint y, uint k) returns(uint)
等同(x * y) % k。
20.2.定长字节数组属性
- <bytesN>.length
获取bytesN定长字节数组的长度,值为uint类型。
contract TestBytesN{
function getLength() public pure returns(uint, uint){
bytes2 byA = "ab";
bytes4 byB = "ab";
return (byA.length, byB.length);
}
}
20.3.函数属性
- <function>.selector
获取function函数选择器,值为bytes4类型。
函数选择器(又称函数签名),目的是通过函数选择器使以太坊虚拟机找到相应的函数。函数选择器本质上是取函数keccak256哈希的前4字节,如:bytes4(keccak256(“funName(uint256,string)”),其中双引号括起来的是函数名称加上由括号括起来的参数类型列表,参数类型间由一个逗号分隔开,且没有空格,对于uint和int参数类型必须使用uint256和int256。
注意:public和external函数支持selector属性,而internal和private函数不支持。
// 测试selector属性的合约
contract TestSelector{
function () external pure pubVar = this.pubFun;
function () external pure extVar = this.extFun;
function () internal pure intVar = intFun;
function () internal pure priVar = priFun;
function pubFun() public pure{}
function extFun() external pure{}
function intFun() internal pure{}
function priFun() private pure{}
// 获取public函数的选择器
function testPub() public view returns(bytes4, bytes4, bytes4){
// 通过函数指针调用selector属性以获取pubFun函数的函数选择器
bytes4 selectorA = pubVar.selector;
// 通过函数名称调用selector属性以获取pubFun函数的函数选择器
bytes4 selectorB = this.pubFun.selector;
// 通过keccak256函数获取pubFun函数的函数选择器
bytes4 selectorC = bytes4(keccak256("pubFun()&#