阅读(230) (12)

抽象合约

2022-05-13 11:17:29 更新

当至少其中一个功能未实现或未为其所有基本合约构造函数提供参数时,必须将合约标记为抽象。即使不是这种情况,合同仍可能被标记为抽象,例如当您不打算直接创建合同时。抽象契约类似于接口,但接口在它可以声明的内容方面受到更多限制。

使用abstract关键字声明抽象合约,如以下示例所示。请注意,该合约需要定义为抽象的,因为utterance()声明了函数,但没有提供实现(没有给出实现主体)。{ }

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;

abstract contract Feline {
    function utterance() public virtual returns (bytes32);
}

这样的抽象合约不能直接实例化。如果抽象合约本身确实实现了所有定义的功能,这也是正确的。抽象合约作为基类的用法如下例所示:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.6.0 <0.9.0;

abstract contract Feline {
    function utterance() public pure virtual returns (bytes32);
}

contract Cat is Feline {
    function utterance() public pure override returns (bytes32) { return "miaow"; }
}

如果合约继承自抽象合约,并且没有通过覆盖实现所有未实现的功能,则也需要将其标记为抽象。

请注意,没有实现的函数与函数类型不同,尽管它们的语法看起来非常相似。

没有实现的函数示​​例(函数声明):

function foo(address) external returns (address);

类型为函数类型的变量的声明示例:

function(address) external returns (address) foo;

抽象契约将契约的定义与其实现分离,提供更好的可扩展性和自文档化,并促进模板方法等模式和消除代码重复。抽象契约的用处与在接口中定义方法的用处相同。这是抽象合约的设计者说“我的任何孩子都必须实现这个方法”的一种方式。

笔记

抽象合约不能用未实现的虚函数覆盖已实现的虚函数。