欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 财经 > 金融 > 【区块链安全 | 第三十篇】合约(四)

【区块链安全 | 第三十篇】合约(四)

2025/4/18 0:34:27 来源:https://blog.csdn.net/2301_77485708/article/details/147039870  浏览:    关键词:【区块链安全 | 第三十篇】合约(四)

文章目录

  • 合约
    • 继承
      • 函数重写(Function Overriding)
      • 修饰符重写(Modifier Overriding)
      • 构造函数(Constructors)
      • 基合约构造函数的参数
      • 多重继承与线性化
      • 继承相同名称的不同成员类型

在这里插入图片描述

合约

继承

Solidity 支持多重继承,包括多态性。

多态性意味着函数调用(无论是内部的还是外部的)总是会执行继承体系中最底层合约中具有相同名称(和参数类型)的函数。这必须在继承体系中的每一个函数上显式启用,使用 virtualoverride 关键字。

可以通过显式指定合约名调用继承体系中更高层的函数,例如:ContractName.functionName(),或者使用 super.functionName() 调用继承结构中上一级的函数(参考下文中“扁平化继承结构”)。

当一个合约继承其他合约时,只会在区块链上创建一个合约实例,所有父合约的代码会被编译进这个创建的合约中。这意味着对父合约函数的所有内部调用只是普通的内部函数调用(例如 super.f(...) 会使用 JUMP 而不是消息调用)。

状态变量遮蔽(shadowing)会被视为错误:如果任何一个父合约中已经声明了变量 x,子合约中就不能再声明同名变量。

Solidity 的继承系统整体上类似 Python 的继承,尤其是对多重继承的处理,但也存在一些差异。

具体示例如下:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;contract Owned {address payable owner;constructor() { owner = payable(msg.sender); }
}// 使用 `is` 关键字派生自另一个合约。
// 派生合约可以访问所有非 private 的成员,包括 internal 函数和状态变量。
// 这些成员无法通过 `this` 关键字从外部访问。
contract Emittable is Owned {event Emitted();// 使用 `virtual` 关键字表示该函数可以被子类重写。function emitEvent() virtual public {if (msg.sender == owner)emit Emitted();}
}// 这些抽象合约只是为了让编译器知道接口。注意没有函数体的声明。
// 如果一个合约未实现所有函数,就只能作为接口使用。
abstract contract Config {function lookup(uint id) public virtual returns (address adr);
}abstract contract NameReg {function register(bytes32 name) public virtual;function unregister() public virtual;
}// 支持多重继承。注意:`Owned` 同时是 `Emittable` 的父类,
// 但在最终合约中只会有一个 `Owned` 实例(类似 C++ 的虚继承)。
contract Named is Owned, Emittable {constructor(bytes32 name) {Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);NameReg(config.lookup(1)).register(name);}// 函数可以通过相同的名称和参数类型进行重写。// 如果返回值类型不一样,将导致编译错误。// 无论是内部调用还是消息调用,都会考虑重写关系。// 如果你要重写函数,必须使用 `override` 关键字。// 如果这个函数还需要被其他合约重写,则还需要再次声明 `virtual`。function emitEvent() public virtual override {if (msg.sender == owner) {Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);NameReg(config.lookup(1)).unregister();// 仍然可以调用被重写的父类函数。Emittable.emitEvent();}}
}// 如果构造函数需要参数,则必须在派生合约的构造器中提供,
// 可以在构造函数声明中传参,也可以通过修饰器风格传参。
contract PriceFeed is Owned, Emittable, Named("GoldFeed") {uint info;function updateInfo(uint newInfo) public {if (msg.sender == owner) info = newInfo;}// 这里只声明 `override` 而不是 `virtual`,// 意味着继承自 PriceFeed 的

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词