1、solidity
类的多继承、重写
solidity
类具有多继承的特性:
1 2 3 4 5 6 7 8 9 10 11 12 13
| pragma solidity ^0.4.19
contract Animal1 { uint age; }
contract Animal2 { string weight; }
contract Dog is Animal1, Animal2 { /** Dog 会继承 Animal1 及 Animal2 两个类 */ }
|
重写与其他语言相通,即子类的同名函数会覆盖从父类继承的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| pragma solidity ^ 0.4 .19;
contract Animal { function testFunc() public pure returns(string) { return "Animal testFunc"; } }
contract Dog is Animal { function testFunc() public pure returns(string) { return "Dog testFunc"; } }
|
2、solidity
函数的访问权限
solidity
函数分为四种访问权限:
private
: 私有函数。内部正常访问,外部无法访问,子类无法继承。
internal
: 内部函数。内部正常访问,外部无法访问,子类可继承。
public
: 公共函数。内部正常访问,外部正常访问,子类可继承。
external
: 外部函数。内部不能访问,外部正常访问,子类可继承。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| pragma solidity ^0.4.19;
contract Animal { function testPublic() public pure returns (string) { return "public"; } function testPrivate() private pure returns (string) { return "private"; } function testInternal() internal pure returns (string) { return "internal"; } function testExternal() external pure returns (string) { return "external"; } function f() public pure { testPublic(); testInternal(); testPrivate(); } }
contract Dog is Animal { }
|
3、solidity
函数中pure
、view
、constant
的区别
solidity
函数的完整声明格式为:
function 函数名(参数) public|private|internal|external pure|view|constant 无返回值|returns (返回值类型)
首先来个测试案例,根据编辑器提示补齐函数类型,然后总结不同之处:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| pragma solidity ^0.4.19;
contract Animal { string homeAddress = "北京市"; uint weight; function getAge() public pure returns (uint) { return 30; } function getCurrentAddress() public view returns (address) { return msg.sender; } function getHomeAddress() public view returns (string) { return homeAddress; }
function setWeight(uint w) public { weight = w; } function getWeight() public constant returns (uint) { weight = 200; return weight; } }
|
结论如下:
- 只有当函数有返回值的情况下,才需要使用
pure
、view
、constant
pure
: 当函数返回值为自变量而非变量时,使用pure
view
: 当函数返回值为全局变量或属性时,使用view
constant
: 可以理解为view
的旧版本,与view
是等价的
如果一个函数有返回值,函数中正常来讲需要有 pure
、view
或constant
关键字,如果没有,在调用函数的过程中,需要主动去调用底层的call方法。
注:如果一个函数中带了关键字view
或constant
,就不能修改状态变量的值。但凡是是带了这两个关键字,区块链就默认只是向区块链读取数据,读取数据不需要花gas,但是不花gas就不可能修改状态变量的值。写入数据或者是修改状态变量的值都需要花费gas。
4、truffle初识
truffle
是以太坊solidity
编程语言的开发框架。
1.安装truffle
cnpm i -g truffle
2.创建项目工程
1 2
| mkdir truffle && cd truffle truffle init
|
3.项目结构
contracts
目录下存的是solidity
合约代码
migrations
中存的是js脚本
test
中存的是测试用例
4.编写代码、部署、调试
contracts
中新建Hello.sol
文件,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| pragma solidity ^0.4.17;
contract Hello {
string weight = "18cm"; string height = "180cm";
function getAge() public pure returns (uint){ return 30; }
function getWeight() public view returns (string) { return weight; }
function getHeight() public constant returns (string) { return height; }
function test() public returns (uint) { return 250; } }
|
注意:
- 类名
Hello
需要跟文件名Hello.sol
保存一致
Migrations.sol
文件不能删除
然后在migrations
目录下添加对应的js脚本2_depoly_hello.js
:
1 2 3 4 5
| var myHello = artifacts.require("./Hello.sol");
module.exports = function(deployer) { deployer.deploy(myHello); };
|
代码添加完后,打开终端,切换到项目所在路径,执行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| //启动测试网络 truffle develop
//编译 compile
//将合约部署到本地测试网络,成功后会返回合约地址(如:0x75c35c980c0d37ef46df04d31a140b65503c0eed) migrate
//通过合约地址,得到合约对象,赋值给变量c var c; Hello.at('0x75c35c980c0d37ef46df04d31a140b65503c0eed').then((obj) => { c = obj; })
//调用合约暴露的方法 c.getAge()
//如果合约中暴露出的有返回值的函数,没有用 pure/view/constant 声明,则需要调用底层的 call 方法才能调用方法 //如上面代码中的test方法 c.test.call()
//修改完代码,编译后,重新部署时需重置之前的合约 migrate --reset
|
补充:调用migrate
编译之后会build
文件夹,存储的是编译之后生成的json
文件,而这个json
文件就是合约部署在虚拟机中的形式。
编译生成的的json
文件中,有两个重要的额键值:
abi
:通俗讲,abi
与api
类似,都是接口。abi
是合约的二进制接口。
bytecode
:是合约代码的16进制码
通过abi
及bytecode
就能完成合约的部署。
5、基本值类型、引用类型
uint
为值类型,只能深拷贝
string
为引用类型,既可以深拷贝,也可以浅拷贝
uint
及string
深拷贝(默认的声明方式即为深拷贝):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| string a = "100"; uint b = 100;
// 浅拷贝 // string aa 等同于 string memory aa function m(string aa) private { aa = "1000"; } function n(uint bb) private { bb = 1000; }
function f() public { m(a) n(b) }
|
string
类型浅拷贝(加storage
关键字):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| string a = "100"; function f() public { m(a) }
function m(string storage aa) private { bytes(aa)[0] = '6'; }
function getA() public view returns (string) { return a; }
|