Solidity语言学习(5)——值类型与引用类型(其二)

合约类型

每个合约都定义自己的类型。(不再是地址派生出的了)你可以隐式的将合约转化为他继承的合约,也可以显示的将他们转化或转化自address类型。

0.5.0版本后合约不再是地址类型导出的了,但仍可以显示的转化为地址类型。
如果你声明了一个本地合约类型变量(MyContract c),你可以在这个合约上调用函数。但是需要小心使用其他同样的合约类型对其赋值。
(这一段是最新版中添加的内容,看不太懂,原文如下)

Every contract defines its own type. You can implicitly convert contracts to contracts they inherit from, and explicitly convert them to and from the address type.

Note

Starting with version 0.5.0 contracts do not derive from the address
type, but can still be explicitly converted to address.

If you declare a local variable of contract type (MyContract c), you can call functions on that contract. Take care to assign it from somewhere that is the same contract type.

You can also instantiate contracts (which means they are newly created). You can find more details in the ‘Contracts via new’ section.

The data representation of a contract is identical to that of the address type and this type is also used in the ABI.

Contracts do not support any operators.

The members of contract types are the external functions of the contract including public state variables.

定长 字符数组(Fixed-size byte arrays)

bytes1,… , bytes32, 允许值以步长1 递增。byte默认表示 byte1.

运算符
比较: <= , < , ==, != , >= , >, 返回值为bool类型。
位运算符: &,|,^ (异或) ,- 非, <<(左移位), >>(右移位)
序号访问: 与大多数语言一样,取值范围为[0,n)

移位运算与整数类似,移位运算的结果的正负取决于操作符左边的数,且不能进行负移位。
例如,可以 -5 <<1 , 不可以 5<<-1

成员变量
.length 表示这个字符数组的长度(只读)

变长(动态分配大小)字节数组(Dynamically-sized byte array)

  • bytes:动态分配大小字节数组,参加Arrays,不是值类型,是引用类型。
  • strings:动态分配大小utf8编码的字符类型。不是值类型,同上。

一个好的使用原则:

  • bytes 用来存储任意长度的字节数据,string 用来存储任意长度的UTF8编码的字符串数据
  • 如果长度可以确定,尽量使用定长的如 byte1 到 byte32 中的一个,因为这样更省空间

有理数和整型常量(Rational and Integer Literals)

也有把Literals称为字面量的

整型常量是有一系列0-9的数字组成,10进制表示,比如:8进制是不存在的,前置0在Solidity中无效的。

10进制小数常量带了一个. , 在 . 的两边至少有一个数字,有效的表示如:1.,.1,1.3

科学符号也支持,基数可以是小数,指数必须是整数,有效的表示如:2e10,,-2e10,2e-10,2.5e1 。

数学常量表达式本身支持任意精度,也就是可以不会运算溢出,或除法截断。但当它被转换成对应的非常量类型,或者将他们与非常量进行运算,则不能保证精度了。

如:(2***800 +1) - 2***800的结果为1(uint8整类),尽管中间结果已经超过计算机字长。另外:.5*8的结果4,尽管有非整形参与了运算。

只要操作数是整形,整型支持的运算符都适用于整型常量表达式。
如果两个操作数是小数,则不允许进行位运算,指数也不能是小数。

注意:
solidity对每一个有理数都有一个数值常量类型。整数常量和有理数常量从属于数字常量。所有的数字常表达式的结果都属于数字常量。所以1+2和2+1都属于同样的有理数的数字常量3

警告:
整数常量除法,在早期的版本中是被截断的,但现在可以被转为有理数了,如5/2的值为2.5

注意:
数字常量表达式,一旦其中含非常量表达式,它就会就转为一个非常量类型。下面代码中表达式的结果将会被认为是一个有理数:

uint128  a = 1;
uint128  b = 2.5 + a +0.5;

上述代码编译不能通过,因为b会被编译认为是小数型。

字符串常量

字符串常量是指由单引号,或双引号引起来的字符串(“foo” or ‘bar’)。字符串并不像c语言,包含结束符,”foo“这个字符串大小仅为3字节。和整数常量一样,字符串的长度类型可以是变长的。字符串可以隐式的转换为byte1,。。。byte32如果合适,也会转为bytes 或 String。

字符串常量支持转义字符,比如\n,\xNN,\uNNN。其中\xNN表示16进制值,最终转换合适的字节.而\uNNNN表示Unicode编码值,最终会转换为UTF8的序列.

十六进制常量(Hexadecimal Literals)

十六进制常量,以关键自hex打头,后面紧跟用单或双引号包裹的字符串,内容是十六进制字符串,如hex”001122ff”.它的值会用二进制来表示.

十六进制常量和字符串常量类似,也可以转换为字节数组.

枚举(Enums)

在Solidity中,枚举可以用来自定义类型.他可以显式的与整数进行转换,但不能进行隐式转换.显式的转换会在隐形时检查数值范围,如果不匹配,将会引起异常.枚举类型应至少有一名成员.

pragma solidity ^0.4.0

contract test {
    enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
    ActionChoices choice;
    ActionChoices constant defaultChoice = ActionChoices.GoStraight;

    function setGoStraight() {
         choice = ActionChoices.GoStraight;
     }

     // Since enum types are not part of the ABI, the signature of "getChoice"
     // will automatically be changed to "getChoice() returns (uint8)"
     // for all matters external to Solidity.The integer type used is just 
     // large enough to hold all enum values, i.e. if you have more values,
     // ' uint16' will be used and so on.
     function getChoice() returns (ActionChoices) {
            return choice;
     }

     function getDefaultChoice() returns (uint) {
            return uint(defaultChoice);
     }
}

程序中段的意思是说,由于自定义Enum不是ABI的一部分,所以返回的值依然是一个uint8(在这里实际上合约中返回的值就是2而不是Gostraight)

函数类型

函数类型是一种表示函数的类型.可以将一个函数赋值给另一个函数类型的变量,也可以将一个函数作为参数进行传递,还能在函数调用中返回函数类型变量.
函数类型有两类:内部(internal) 函数 和 外部(external)函数:

内部函数只能在当前合约内被调用(更具体的说,在当前代码块内,包括内部库函数和继承的函数中),因为它们不能在当前合约上下文的外部被执行.
调用一个内部函数是通过跳转到它的入口标签来实现的,就像在当前合约的内部调用一个函数.

外部函数由一个地址和一个函数签名构成,可以通过外部函数调用传递或者返回.

函数类型的原型如下

function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]

与参数类型相反,返回类型不能为空 _ 如果函数类型不需要返回,则需要删除整个 returns() 部分.

函数类型默认是内部函数,因此internal不需要特别声明.
与此相反的是,合约中的函数本身默认是 public 的,只有当它被当做类型名称时,默认才是内部函数.

两种函数类型A和B可以隐式的转化(如A转化到B)当且仅当他们的参数类型是一致的,他们的返回类型是一致的,并且他们的外部/内部函数性质也是一致的,且A的状态易变性不会比B更苛刻.有一点特殊的地方是:

  • pure 函数可以被转化为 view 和 non-payable 函数
  • view函数可被转换为 non-payable 函数
  • payable 函数 可以被转化为non-payable函数

其他的转化均不可行.

有两种方法可以访问当前合约中的函数:一种是直接使用它的名字,f,另一种是使用 this,f .
前者适用于内部函数, 后者适用于外部函数.

如果当函数类型的变量还没有初始化时就调用它的话会引发一个异常.
如果在一个函数被 delete 之后调用它也会发生相同的情况.

如果外部函数类型在solidity的上下文环境以外的地方使用,它们会被视为 function 类型.
该类型将函数地址紧跟其函数标识一起编码为一个bytes24类型.

请注意,当前合约的 public (或external)函数既可以被当做内部函数也可以被当做外部函数使用.如果想将一个函数当做内部函数使用,就用f调用,否则就用this,f调用.

除此之外,public(或external)函数也有一个特殊的成员变量称作 selector,可以返回 ABI函数选择器

pragma solidity ^0.4.16

contract Selector{
      function f() public view returns (bytes4) {
          return this.f.selector ;
       }
}

猜你喜欢

转载自blog.csdn.net/weixin_42595515/article/details/81914276