这篇文章主要介绍了Solidity 类特性 ,文中通过代码以及文档配合进行讲解,很详细,它对在座的每个人的研究和工作具有很经典的参考价值。 如果需要,让我们与区块链资料网一起学习。

https://www.interchains.cc/24662.html

Solidity 类特性是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,Solidity 类特性学习起来其实是很简单的,

不多的几个较为抽象的概念也很容易理解,之所以很多人感觉Solidity 类特性比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难

Solidity 类特性

  • Solidity

本文讨论 Solidity 的类特性

  • 原文链接:https://medium.com/coinmonks/class-features-provided-by-solidity-84ee97840666 作者:Jules Goddard
  • 译文出自:登链翻译计划
  • 译者:翻译小组
  • 校对:Tiny 熊
  • 本文永久链接:learnblockchain.cn/article…

本文讨论 Solidity 的类特性,Solidity 是以太坊eth区块链blockchain的默认智能合约语言。

背景

在 Datona 实验室的 Solidity Smart-Data-Access-Contract(S-DAC)模板的开发和测试过程中,我们探索了使用类的技术,就像在传统的面向对象的编程(OOP)语言中一样。例如,我们希望能写出类似这样的代码:

import "ContractOwner.sol"; import "Partners.sol"; contract EasyShare ... {     ContractOwner contractOwner;     Partners partners;      ...     function addPartner(...) public onlyContractOwner {         partners.add(...);     }     ... }

在这个例子中,ContractOwnerPartners 是我们想要使用的类。

一个类将相关的代码和数据封装在一个实体中。

关于这个的实现将在下面的例子中进一步探讨。

为什么在 Solidity 中使用类?

因为我们很习惯在 OOP 开发中使用类,并且想要继续以这种方式来开发,因为它很好用。

对于为什么要用 OOP 编程,其可能的原因有很多。参考wiki中的面向对象编程。

在 Solidity 中使用类有什么好处?

我们发现,OOP 是非常熟悉、自然的,通常可以减少错误率,便于独立测试,并能重用。

在 Solidity 中使用类的缺点是什么?

主要的缺点是可能会使我们不去完全使用 Solidity 的编程范式。

还有人担心,大量导入文件会成为维护的噩梦。

最后,Solidity 合约通常非常简单,而导入文件可能会增加不必要的复杂性、成本和文件管理。

尽管如此,我们认为值得探索各种可能性,即使只是为了拒绝它们。

Solidity 类特性

Solidity 已经有很多与现代 OOP 语言非常不同的特性,如:合约、可支付账号(payable account);执行的 Gas 消耗;永久存储;全局执行等等。

然而,合约不是类,因为Solidity有函数调度程序和其他开销,调用其他合约的函数是非常昂贵的。我在另一篇文章中有提到过“Solidity 函数的 Gas 消耗 ”。

Solidity 提供了哪些功能来实现将代码和数据封装在类里呢?

下面我们将开始探讨:

1) 导入文件 2) 合约继承 3) 将库附加到结构体

在所有这些功能中,数据和函数都可以使用类似类的点符号。例如:myClass.myFunction(myArgument)。在某些情况下,也可以不用指定类。

1)导入文件

有一下几种情况,我们应该作为一个单独的实体文件保存,然后再导入它们,例如:

1.1) 其他合约

在 Solidity 中,合约有可能创建其他合约。除了为测试而创建的临时合约外,那些其他合约似乎很有可能是在不同的文件中被定义:

import "OtherContract.sol"; contract MyContract ... {     OtherContract otherContract;     constructor(...) public ... {         otherContract = new OtherContract(...);     }     ... }

1.2) 继承的合约

在 Solidity 中,也可以继承合约。并且,除了为测试而创建的临时合约外,继承的合约似乎很有可能被重复使用,所以在一个单独的文件中定义很重要,在下面(2)会进一步探讨。

1.3)库

在 Solidity 中也可以创建库,库函数可以是外部或内部的。任何包含外部函数的库大概都是为了被其他合约重用,所以应该在一个独立的文件中定义。

import "SortLibray.sol"; contract MyContract ... {     MyStruct data;     ...     function sortData(...) internal ... {         SortLibrary.sort(data);     }     ... }

包含内部函数的库将与合约的字节码一起被打包。这些将在(3)中讨论。

2) 合约继承

在 Solidity 中,有两种方式可以有效地提供类特性,一种是继承基础合约

被继承的基础合约是一个普通合约,包含数据和可以作用于这些数据的函数,但通常是不完整的,或者说只是完整合约的一个片段。恰当的文件命名习惯是很有用,可以清楚知道哪些合约是作为可继承的基础合约。

我们还可以把继承当做对象组合来使用,这在下面的例子中会讲到。

3) 将库附加到结构体

这是另一种有效提供类特性的方式,这种方式是创建一个结构体并附加一个库,库中的函数接受该结构体。这就是将一个库附加到一个类型(通常是一个结构体)。

在希望使用该类的合约中,声明了结构体的变量,并可提供结构体作为参数来调用库函数。

Solidity 提供了一个编译器指令,以支持使用点符号调用库函数,这就是using for( using library for struct)。这个功能也可以用于扩展标准类型,例如, using NumbersLib for uint

看看下面的例子。

一些使用 Solidity 类特性的例子

我们用一个简单的合约来演示与伙伴分享某部分内容。可能是一家公司的股份,也可能是一项资产的所有权,或者其他什么,都没关系。本文中没有任何财务方面的考虑。

这是我们为一家金融技术公司写的概念验证合约的修正摘录。

Solidity 类特性

这个版本的合约,使用一个叫做ContractOwner的基础合约和一个叫做Partners的组件类。

import "ContractOwner.sol"; import "Partners.sol"; contract EasyShareLib is ContractOwner {      using PartnersFuns for Partners;     Partners partners;     uint public total;     uint public allocated;      constructor(uint _total) public {         require(_total > 0, "Supplied total must be > 0");         total = _total;     }      function addPartner(address account, string memory info)      public onlyContractOwner {         partners.add(account, info);     }      function transferToPartner(address account, uint amount)      public onlyOwner {         require((amount > 0) && (amount <= total - allocated));         partners.incBalance(account, amount);         allocated += amount;     }      function getPartnerBalance(address account) public view      returns (uint) {         return partners.getBalance(account);     }      function getPartnerInfo(address account) public view      returns (string memory) {         return partners.getInfo(account);     } }

注意,我们从不同的文件中导入了这些类。

ContractOwner是一个继承的基类,PartnersFuns是一个(内部)函数库,它附在Partners结构体上。后面列出了这些文件。

没有 Solidity 类特性的例子

对比上面的 EasyShareLib 版本的合约,下面的EasyShare版本没有继承基础合约,也没有附加库到结构体。

contract EasyShare {     // ContractOwner     address private contractOwner = msg.sender;      modifier onlyOwner() {         require(msg.sender == contractOwner, "Not permitted");         _;     }     // Partners     struct Partner {         address account;         string info;         uint balance;     }      Partner[] partners;     uint public total;     uint public allocated;      constructor(uint _total) public {         require(_total > 0, "Supplied total must be > 0");         total = _total;     }      function findPartner(address account) internal view     returns (int index) {         uint length = partners.length;         for (uint u = 0; u < length; u++) {             if (partners[u].account == account) return int(u);         }         return -1;     }      function addPartner(address account, string memory info)      public onlyContractOwner {         require(findPartner(account) < 0, "Already exists");         partners.push(            Partner({account: account, info: info, balance: 0}));     }      function transferToPartner(address account, uint amount)      public onlyOwner {         require((amount > 0) && (amount <= total - allocated));         int index = findPartner(account);         require(index >= 0, "This partner is unknown");         partners[uint(index)].balance += amount;         allocated += amount;     }      function getPartnerBalance(address account) public view      returns (uint) {         int index = findPartner(account);         require(index >= 0, "This partner is unknown");         return partners[uint(index)].balance;     }     function getPartnerInfo(address account) public view      returns (string memory) {         int index = findPartner(account);         require(index >= 0, "This partner is unknown");         return partners[uint(index)].info;     } }

这个例子中没有使用导入文件,总体上还比较简洁,但没有采用可重复使用的合约和库。

导入文件

Solidity 类特性

ContractOwner.sol导入EasyShareLib中。

contract ContractOwner {     address private contractOwner = msg.sender;     modifier onlyContractOwner() {         require(msg.sender == contractOwner, "Not permitted");         _;     }     ... }

Partners.sol也被导入EasyShareLib

struct Partner {     address account;     string info;     uint balance; } struct Partners {     Partner[] a; } library PartnersFuns {     function find(Partners storage partners, address account)     internal view returns (int index) {         uint length = partners.a.length;         for (uint u = 0; u < length; u++) {             if (partners.a[u].account == account) return int(u);         }         return -1;     }     function add(Partners storage partners, address account,      string memory info) internal {         require(find(partners, account) < 0, "Already added");         partners.a.push(Partner(account, info, 0));     }     function incBalance(Partners storage partners, address account,     uint amount) internal {         int index = find(partners, account);         require(index >= 0, "This partner account is unknown");         partners.a[uint(index)].balance += amount;     }     function getBalance(Partners storage partners, address account)      internal view returns (uint) {         int index = find(partners, account);         require(index >= 0, "This partner account is unknown");         return partners.a[uint(index)].balance;     }     function getInfo(Partners storage partners, address account)      public view returns (string memory) {         int index = find(partners, account);         require(index >= 0, "This partner account is unknown");         return partners.a[uint(index)].info;     } }

测试

要确保两个版本的 EasyShare 合约行为正确,方式相同。

Gas 消耗量

我们测量了创建合约的 Gas 成本,然后添加10个账户,并向10个账户中的每个账户转移一些股份,然后获取10个账户中每个账户的余额和信息字符串。我们使用了我在另一篇文章——Solidity 函数的Gas 消耗 中所分享的 Gas 消耗测量方法。

Solidity 类特性

两个合约的消耗基本相同,除了CreateGetInfoEasyShareLib中比EasyShare高一点。

Creat成本比较高,因为调用库函数有更多的字节码。

GetInfo的成本较高,因为它是一个返回字符串的函数。通过额外的函数来访问库,字符串必须被复制两次。

GetInfo也比GetBalance高。这清楚地表明了使用字符串的代价,它是参考变量,而不是价值数据项。

结论

使用 Solidity 的特性来导入包含继承基础合约的文件,并将库附加到结构体,这提供了我们在本文开头所期望的大部的分类的功能。

我们推荐将它们应用于快速开发的实验性合约。

对于生产合约,你可能希望考虑将导入的文件扩展到合约中。

Jules Goddard是Datona实验室的联合创始人,他们提供智能合约来保护你的数字信息不被滥用。


本翻译由 Cell Network 赞助支持。

  • 发表于 2小时前
  • 阅读 ( 33 )
  • 学分 ( 77 )
  • 分类:Solidity

部分转自网络,侵权联系删除www.interchains.cchttps://www.interchains.cc/24662.html

区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 ! QQ3039046426
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » Solidity 类特性

提供最优质的资源集合

立即查看 了解详情