3.10 solidity数据结构详解

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

你可能感兴趣的:(区块链)