1. Solidity数据结构:数组、枚举、映射/字典、结构体
a. 枚举类型(Enums)
i. 枚举类型是在Solidity中的一种用户自定义类型。他可以显示的转换与整数进行转换,但不能进行隐式转换。显示的转换会在运行时检查数值范围,如果不匹配,将会引起异常。枚举类型应至少有一名成员。
ii. 与其它编程语言一样、枚举类型默认从0开始
b. 字节数组(fixed byte arrays)
i. 定长字节数组:byte1,……,byte32,允许值以步长1递增,默认byte为byte1
1. 运算符:
a. 比较:<=,<,==,!=,>=和>
b. 位运算符:&,|,(^异或),(~非)
2. 支持下标访问,取值[0,n),n表示长度
3. .length:表示这个字节数组的长度---只读(长度不可变)
4. 内部字节不可变
ii. 动态字节数组:
1. Bytes:动态长度的字节数组,参见数组(Arrays)。非值类型
2. String:动态长度的UTF-8编码的字符类型,参见数组(Arrays)。非值类型
3. 使用原则:
a. 如果想要存储UTF-8的字符串数据,使用string,如果想要存储任意长度的字节数据,使用bytes
b. 如果长度确定,尽量使用byte1-byte32中的一个,可以节省空间
c. 数组
i. 数组可以声明时指定长度,或者是变长的。对storage的数组来说,元素类型可以是任意的,类型可以是数组,映射类型,数据结构等。但对于memory的数组来说。如果函数是对外可见的,那么函数参数不能是映射类型的数组,只能是支持ABI的类型
ii. 声明方式
1. 定长:T[K]
2. 不定长:T[]
3. 二维数组:uint [][5]x
a. 注意,在solidity中,多给数组的行列位置和大多数编程语言是相反的
i. uint[3][5]x代表数组X是5行3列
ii. Uint[][5]x代表数组X有5行,每一行的列是一个动态数组
iii. 类型为数组的状态变量,可以标记为public类型,从而让Solidity创建一个访问器,如果要访问数组的某个元素,指定数字下标就好了。
iv. 创建数组:可使用new关键字创建一个memory的数组。与stroage数组不同的是,你不能通过.length的长度来修改数组大小属性。
v. 字面量及内联数组
vi. 数组字面量,是指以表达式方式隐式声明一个数组,并作为一个数组变量使用的方式。
1. 通过数组字面量,创建的数组是memory的,同时还是定长的。元素类型则是使用刚好能存储的元素的能用类型。
2. 定长数组,不能与变长数组相互赋值。
vii. 数组的属性和方法
1. 数组有一个.length属性,表示当前的数组长度。storage的变长数组,可以通过给.length赋值调整数组长度。memory的变长数组不支持。
2. push方法,storage的变长数组和bytes都有一个push(),用于附加新元素到数据末端,返回值为新的长度。
d. 映射
i. 映射或字典类型,一种键值对的映射关系存储结构。定义方式为mapping(_KeyType => _KeyValue)。键的类型允许除映射,动态数组,合约,枚举,结构体之外的所有类型,值的类型无限制。
ii. 映射可以被视作为一个哈希表,其中所有可能的键已被虚拟化的创建,被映射到一个默认值(二进制表示的零)。但在映射表中,我们并不存储键的数据,仅仅存储它的keccak256哈希值,用来查找值时使用。所以说 映射没有长度,键集合(或列表),值集合(或列表)这样的概念。
iii. solidity中,字典无法迭代(考虑自己实现)
e. 结构体
i. 结构体是solidity中的自定义数据类型,其中可以包含字符串,整形等基本的数据类型,以及数组,映射,结构全等复杂的类型
2. Solidity地址与映射、全局单位、转账
a. 地址(Address)
i. 地址类型是solidity专有的类型,它代表以太坊地址的长度,大小20个字节,160位,所以可以用一个uint160编码。地址是所有合约的基础,所有的合约都会继承地址对象,也可以随时将一个地址串,得到对应的代码进行调用。当然地址代表一个普通帐户时,就没有这些功能了。
ii. 从版本0.5.0开始,合约不再是从地址类型派生的,但仍可以显式转换为地址。
iii. 支持的运算符:<=,<,==,!=,>=和>
iv. 成员
1. 属性:
a. balance,通过balance属性可以得到一个地址的余额、如果是想要得到当前地址的余额,可以直接通过this进行调用:this.balance,address(this).balance。
b. Transfer,从合约发起方发送定量的wei到给定的地址,如果抛出失败,补助2300GAS,GAS补助不可调节
2. 函数
a. Send():从合约发起方向某个地址发送货币(单位是wei 一个eth等于10^18wei),如果抛出失败,补助2300GAS,GAS补助不可调节
i. 注意:在以前我们通常使用this.address的方式来获取当前合约地址,但是,随着solidity的改进,现在通常使用address(this)的方式。
b. Call()、Delegatecall()、Callcode():都是底层的消息传递调用,除非不得已,否则不建议使用,因为调用这三个合约,意味着有可能会把你合约的控制权交给对方。
b. 全局变量
i. 全局变量可以在合约脚本中的任何地方使用
ii. solidity内建的全局变量:
This 合约地址的引用
This.balance 余额
This.someFunction() 通过外部方式调用函数
Msg.sender 发送者的地址
Msg.value 发送给合约的以太币数量,单位为wei
Msg.data bytes,完整的调用数据
Msg.gas 剩余gas
Tx.origin 交易发送者的地址
Tx.gasprice gas的价格
Now 当前时间=block.timestamp
Block.number 当前区块号
Block.difficulty 当前区块难度
Block.blockhash(1) 给定区块号的hash值(byte32),只支持最近的256个区块
Block.coinbase 当前区块的矿工地址
Block.gasLimit(); 当前区块的gaslimit
Block.timestamp 当前区块的时间戳
3. Solidity控制语句
a. Solidity中支持if-else, while, do-while,for,break,continue,return,?:(三目运算)
4. Solidity面向对象编程
a. 面向对象编程:面向对象的概念是针对于面向过程而言的、也是我们常说的OO编程,它一种对现实世界理解和抽象的方法。最初的面向对象专指在程序中采用"封装","继承","多态"的设计方法,发展到今天,面向对象的概念和应用已超越了程序设计和软件开发
b. solidity的面向对象
i. 继承:
1. 什么是继承:继承就是类与类之间一种特殊与一般的关系
2. 通过"is"关键字来继承另一个合约。派生合约可以访问父类合约所有的非private类型的变量,包括内部函数和状态变量,但不能通过"this"调用
3. 继承支持传递参数
4. 多重继承:solidity允许多重继承,但在多重继承中不能出现重名合约。当一个合约从多个其它合约那里继承,在区块链上仅会创建一个合约,在父合约里的代码会复制来形成继承合约(也就是将父类的代码拷贝到子类中)。
ii. 抽象
1. 抽象函数是没有函数体的的函数,这样的合约不能通过编译,即使合约内也包含一些正常的函数。但它们可以做为基合约被继承。
iii. 接口(interface)
1. 接口与抽象合约类似,与之不同的是,接口内没有任何函数是已实现的,它有如下限制:
a. 不能继承其它合约,或接口
b. 不能定义构造函数
c. 不能定义变量
d. 不能定义结构体
e. 不能定义枚举
2. 如果我们的合约需要和区块链上的其它合约对话,则需要先定义一个接口
iv. 库
1. 库是一种不同类型的合约,没有存储,不拥有以太币。
2. 没有payable,没有fallback函数
v. Import
1. 概念:导入其它源文件
2. 语法
a. Import "filename":从filename中导入所有的全局symbols到当前全局范围
b. Import * as symbolName from "filename":创建新的全局symbol symbolName,其成员都是来自“filename”的全局symbols
c. Import {symbol1 as alias,symbol2} from "filename":创建新的全局symbols“alias”和“symbol2”,它将分别从”filename” 引入symbol1 和 symbol2
d. import "filename" as symbolName 等价于 Import * as symbolName from "filename"
学院Go语言视频主页
https://edu.csdn.net/lecturer/1928
清华团队带你实战区块链开发
扫码获取海量视频及源码 QQ群:721929980