Solidity 类特性

本文讨论 Solidity 的类特性

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

背景

在 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 类特性的例子

我们用一个简单的合约来演示类特性技术。

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


import "ContractOwner.sol";
import "Partners.sol";
co...

剩余50%的内容订阅专栏后可查看

0 条评论

请先 登录 后评论
翻译小组
翻译小组

首席翻译官

92 篇文章, 14053 学分