Solidity基础五

这篇具有很好参考价值的文章主要介绍了Solidity基础五。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

暂时的一事无成也代表将来万事皆有可能!

目录

一、对Solidity文件的理解

二、Solidity的导sol文件(库、合约)

三、Solidity的继承

1.继承的分类

2.继承的可见性 

3.父合约构造函数的传参

4.调用父合约成员

5.重写

四、Solidity的抽象合约

五、Solidity接口合约

实现接口

六、Solidity的库

库合约的存在形式

七、Solidity的对象 


Solidity基础五

一、对Solidity文件的理解

Solidity文件是Solidity语言文件,里面包含Solidity语言代码,用于编写合约,文件名以.sol结尾。

一个sol文件可以创建(含有)许多的contract(合约),不单单只有一个

那同一个sol文件中的各个合约如何实现交互呢?

不同的sol文件的各个合约又如何进行交互呢?

答案是:继承和对象以及导文件导库

二、Solidity的导sol文件(库、合约)

关键字:import 

格式:import  sol文件名.sol  (文件的相对位置)

可以进行导入外部sol文件,导的sol文件和本身的sol文件相当于变成同一个sol合约 

  

具体操作

    import关键字使用:导入其他源文件

    1. imporot  "solidity文件名"   :导入该文件全局作用域到当前全局作用域中    2.import * as 别名 "solidity文件名"   :

    2.import   "solidity文件名"  as  别名  :导入该文件全局作用域到当前全局作用域中,并起一个文件别名,通过别名可创建导入文件下某一合约的对象,经常用

    3.imoport {合约名 as 别名,合约名} from "solidity文件夹名" :导入导入文件夹名

    下的某几个合约到该文件中

三、Solidity的继承

像java类的继承一样,在solidity中,那就是合约的继承

Solidity 语言是一种面向对象的编程语言,提供了对合约继承的支持,继承是扩展合约功能的一种方式。

Solidity 语言的合约继承通过关键字 is 来完成继承。

继承的关键字:is

 

继承的本质:继承的实现方案是代码拷贝,所以合约继承后,部署到网络时,将变成一个合约,代码从父类拷贝到子类中。

被继承的合约我们称之为父合约(基类合约),继承了的合约称之为子合约(派生合约)

Solidity中合约继承的重要特点

  • 派生合约可以访问父合约所有非私有private的成员,包括内部方法和状态变量。但是不允许使用this(代表需要使用创建对象的形式来访问external的东西)
  • 如果函数名保持不变,则允许函数重写,如果派生合约与父合约函数对应出参和入参类型和个数不同,则将编译将失败(重写的本质是改变函数体)
  • 使用super关键字或父合约名调用父合约函数,或者直接调用
  • 在多重继承的情况下,使用super的父合约函数调用,优先选择被最多继承的合约

1.继承的分类

单继承:

一个合约继承一个合约

例如:

contract X {}

contract A is X{}

多继承

一个合约被多个合约继承

例如

contract X {}

contract A is X{}

contract B is X{}

多层继承

但可以有爷爷,祖先,而这就是多重继承

合约被合约继承,继承的合约又被另一个合约继承

注意事项:

当多重继承合约时,这些父合约中不允许出现相同的状态变量名

当多重继承合约时,这些父合约中允许出现相同的函数名,事件名,修改器名

例如

contract X {}

contract A is X{}

contract B is A{}

多重继承示例

Solidity 语言提供了对合约继承的支持,而且支持多重继承。

Solidity 语言的多重继承采用线性继承方式。继承顺序很重要,判断顺序的一个简单规则是按照“最类似基类”到“最多派生”的顺序指定基类。

第一种情况:基类 X,Y 没有继承关系,派生类 Z 继承了 X,Y。

X  Y
/  \
\  /
 Z

多重继承格式

子合约 is 父合约1,父合约2····{

}

contract X {}

contract A {}

contract B is X,A{}

2.继承的可见性 

子合约不能访问父合约的private修饰的私有成员

子合约可以直接访问访问父合约的所有非私有(public、internal)成员

子合约不能直接访问父合约的external修饰的外部成员,因为子合约不能对父合约的东西使用this,想要访问到就必须创建父合约对象的方式来调用间接访问

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract A{
  uint stateVar;//状态变量默认是internal权限
  function somePublicFun() public{}
  function someInternalFun() internal{}
  function somePrivateFun() private{}
  function someExternalFun() external{}
}

contract B is A{
  function call() public {
    //访问父类的`public`方法
    somePublicFun();

    //访问父类的状态变量(状态变量默认是internal权限)
    stateVar = 10;

    //访问父类的`internal`方法
    someInternalFun();

    //不能访问`private`
    //somePrivateFun();
    A a = new A();
    a.someExternalFun();
  }
}

 3.父合约构造函数的传参

派生的合约初始化前需要调用所有父合约的构造函数,并且还需要提供所有父合约所需的参数

提供父合约构造函数需要的所有参数,有两种提供方式

第一种称

在声明继承的时候

派生合约名 is 父合约名(参数) {        }

此方式对于构造函数是常量情况的时候比较方便,可以直接说明合约的行为

第二种称

在派生合约的构造器中

constructor(参数列表) 父合约名(子合约定义好的参数列表){

}  

注意:如果是多重继承,那么同理

派生合约名 is 父合约名(参数),·····{        }

constructor(参数列表) 父合约名(子合约定义好的参数列表),·······{

}  

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
contract test {
    uint a=1;

    constructor(uint aa) {
        a=aa;
    }

}

contract test1 is test(12) {
    
}

contract test2 is test {
    constructor(uint v) test(v){
    }
}   

 4.重写

允许重写:

函数

不允许重写:

状态变量

在子合约中允许重写函数,但不允许重写函数入参和出参,即参数类型和个数不能修改

重写步骤:

1.父合约要被重写的函数必须加上能被重写修饰符 virtual 

2.子合约重写的函数上面必须加上重写修饰符 override 

 

温馨提示:当父合约里面有两个以上同名方法的时候,子合约必须重写夫合约里面的所有同名方法,格式:override(父合约名,······)

//SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.8.0;

contract test {

    uint a=1;

    function set() virtual public {

        a=2;

    }

}

contract test1 {

    function set() virtual public  {

       

    }

}

contract test2 is test,test1 {

    function set() public override(test,test1){

        super.set();

    }

}

 

温馨提示:

midifier函数修改器(后面讲)也会随着父合约被继承从而被继承,被继承后,在子合约中我们还可以对父合约中的修改器进行重写和使用

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Person{
  string public name;
  uint public age;
  function getSalary() external pure virtual returns(uint){
    return "unkown";
  }
}
contract Employee is Person{
  function getSalary() external pure override returns(uint){
    return 3000;
  }
}

5.调用父合约成员

当一个合约从多个合约继承时,在区块链上只有一个合约被创建,所有基类合约的代码被编译到创建的合约中。这意味着对基类合约函数的所有内部调用也只是使用内部函数调用

1.直接调用和使用(适用于单继承,或者其他继承但名不冲突的情况下)

2. 利用父合约名(这样更好,适用多种类型的继承)

3.super关键字  (使用super可以访问父合约的函数,但不能访问状态变量,如果是多层和多重继承,那么它将调用所有的父类的该名的方法)

使用super调用

使用super调用,格式为:super.<method>。

单继承:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract X {
   function foo() internal pure returns(uint) {
      return 1;
   }
}

contract Z is X {
   function test() external pure returns(uint) {
      // supper 表示父级合约,foo为父级合约的方法名称
      uint result = supper.foo();
      return result;
   }
}

多层、多重继承:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract X {
   event log(string message);

   function foo() public virtual {
      emit log("X.foo");
   }
}

contract Y is X {
   function foo() public virtual override {
      emit log("Y.foo");
      super.foo();
   }
}

contract Z is X {
   function foo() public virtual override {
      emit log("Z.foo");
      super.foo();
   }
}

contract T is Y,Z {
   function foo() public override(Y,Z) {
      super.foo();
   }
}

四、Solidity的抽象合约

抽象合约和普通合约一样,只不过抽象合约里面可以存在未实现的函数(function 函数名() 函数修饰符 ; ),且子类合约必须重写未实现的函数,可以说,如果一个普通合约里面有一个未实现的函数,那么编译会出错,除非加上abstract。或者普通合约必须要求子类做一件事(必须重写某个函数)可以使用抽象合约

关键字: abstract

 

使用格式:

abstract contract 抽象合约名 {

        状态变量;

        未实现的函数;

        ·················

}

 

抽象合约的作用:

抽象合约 abstract 的作用是将函数定义和具体实现分离,从而实现解耦、可拓展性,其使用规则为

简单来说:抽象合约定义后,是专门用来继承用的,它相比于其他的继承做了一种强迫的事情,就是子合约必须重写抽象合约里面的所有函数

abstract还可以避免子合约不对父合约进行构造函数传参的问题

 注意事项

  • 当合约中有未实现的函数时,则合约必须修饰为abstract;
  •  当合约继承的基合约中有构造函数,但是当前合约并没有对其进行传参时,则必须修饰为abstract;
  • abstract合约中未实现的函数必须在子合约中实现
  • abstract合约不能单独部署,必须被继承后才能部署;Solidity基础五

 

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

abstract contract Animal {
    string public species;
    constructor(string memory _base) {
        species = _base;
    }
}

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

    function base(uint _num) public returns(uint, string memory) {
        num = _num;
        return (num, "hello world!");
    }
}

// 由于Animal中的构造函数没有进行初始化,所以必须修饰为abstract
abstract contract Cat1 is Feline, Animal {
    function utterance() public pure override returns (bytes32) { return "miaow"; }
}

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

五、Solidity接口合约

接口本意是物体之间连接的部位。例如:电脑的 usb 接口可以用来连接鼠标也可以连接U盘和硬盘。因此,使用标准的接口可以极大的拓展程序的功能。在 solidity 语言中,接口可以用来接受相同规则的合约,实现可更新的智能合约。

interface 类似于抽象合约,但它们不能实现任何功能。还有其他限制:

  1. 不能继承其他合约或者接口(是接口不能去继承接口和合约,表示它不能被继承)
  2. 不能定义构造器(构造函数)
  3. 不能定义状态变量(变量、结构体、数组、映射、枚举等)
  4. 只能定义普通函数和修改函数
  5. 所有声明的函数必须是 external 的。
  6. 接口里面的函数必须全部实现

  

接口的特点:定义函数的时候它不需要写virtual,且函数修饰符都必须写external

 

接口关键字:interface

定义格式:

interface 接口合约名 {        

        定义接口函数1;

        ·········;

        定义接口函数n;

}

实现接口

实现接口和继承一样,使用关键字is

实现接口函数用override修饰符

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

interface Bank{
function outputMoney(uint _money) external ;
function intputMoney(uint _money) external ; 
}

contract own is Bank {
uint public money;
function outputMoney(uint _money) external override {
    money+=_money;
}

function intputMoney(uint _money) external override {
    money-=_money;
}
}

六、Solidity的库

Solidity 智能合约中通用的代码可以提取到库 library,以提高代码的复用性和可维护性

库 library 是智能合约的精简版,就像智能合约一样,位于区块链上,包含可以被其他合约使用的代码。

库合约内部一般定义成public和internal权限,定义成 external 毫无意义,因为库合约函数只在内部使用,不独立运行。同样,定义成 private 也不行,因为其它合约无法使用。

对比普通合约来说,库有以下限制

  • 无状态变量
  • 不能继承和被继承
  • 不能接收以太币
  • 不能销毁一个库

代表只能有函数 

 

关键字:library

格式:

library 库名{

        库方法

        ·····

}

使用库 library 的合约,可以将库合约视为隐式的父合约,当然它们不会显式的出现在继承关系中。也就是不用写 is 来继承,直接可以在合约中使用。

库的使用

如果库和使用库的合约在同一个sol文件,那么即可直接用

如果库的使用库的合约不在同一个sol文件,那么需要先导库import

第一种使用方式

库名.库合约函数(参数值1,参数值2····)        的方式直接调用库里面的函数 

第二种使用方式

关键字:using ...  for .....

再使用using 库合约名 for 数据类型

使用 using for 语法附着的数据类型,在使用的时候,可以直接用 <variable>.<method> 的形式调用,而且省略代表自己的第一个参数。

格式:

using 库名 for 使用的类型(using 库名 for *  代表附着到全部类型)    

然后使用

格式: 使用的类型数据.库合约内函数名(参数值2,``````)      //该变量默认为第一个参数

温馨提示:using ... for... 的使用必须写在函数外,让其变成状态变量,来对该类型使用

//SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;

library ss{
    function Math(uint _a,uint _b) public pure returns(uint ) {
        if(_a==0 || _b==0){
            return 0;
        }else{
           return (_a*_b);
        }
    } 
}

contract gg {
    uint a=1;
    uint b=0;
    function js() public view returns(uint){
      return  ss.Math(a,b);
    }

    using ss for uint;

    function jss() public view returns(uint){
       return a.Math(b);
    }
}

 

库合约的存在形式

库 library 有两种存在形式:

  •  内嵌(embedded):当库中所有的方法都是internal时,此时会将库代码内嵌在调用合约中,不会单独部署库合约;
  •  链接(linked):当库中含有external或public方法时,此时会单独将库合约部署,并在调用合约部署时链接link到库合约。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library Math {
   function find(uint[] storage arr, uint val) internal view returns(uint){
      for (uint i=0; i<arr.length; i++) {
         if (arr[i] == val) {
            return i;
         }
      }
      revert("not found");
   }
}

contract MathTest {
    //直接使用
    uint[] a;

    uint b;

    function tests() public view {
        Math.find(a,b);
    }

   //using for使用
   // 将 libray Math 附着到类型 uint[]
   using Math for uint[];

   uint[] arr = [1,2,3];

   function test() external view returns(uint){
      return arr.find(2);
   }
}

七、Solidity的对象 

Solidity的对象可以帮助我们访问到非继承合约里面的函数,但不能访问到里面的状态变量,它好比于是两个合约之间的媒人

对象的创建方式

合约名  对象名 = new 合约名() 

这就完成了该合约对象的创建,创建完该对象后,那么创建该对象的合约就可以使用这个对象去调用对象对应合约的函数

常用于

子合约访问父合约external的状态变量和函数

使用非继承关系合约的函数 

  

    具体操作

    1. solidty文件夹名 对象名= new solidity文件夹名()

    2.文件别名 对象名=new 文件别名()

    3.文别名.合约名 对象名 =new 文别名.合约名()

    4. 合约别名 对象名 =new 合约别名()

   5. 合约名 对象名 =new 合约名()

    当然也可以不起别名,那就用solidity文件夹名,或合名文章来源地址https://www.toymoban.com/news/detail-473813.html

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Math {
    int[2] arr;
    function aa() public view returns(int[2] memory){
        return arr;
    }
}

contract MathTest {
    //创建Math合约对象
    Math m = new Math();

    function get() public view returns(int[2] memory){
    //调用Math合约的东西
    return m.aa();
    }
}

到了这里,关于Solidity基础五的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Solidity基础七

    无论风暴将我带到什么岸边,我都将以主人的身份上岸 目录 一、Solidity的单位  1. 货币Ether 2. 时间单位Time 二、地址的形成 三、以太坊的账户 1.内部账户(简称CA) 2.外部账户(简称EOA) 3.内部账户和外部账户的比较  4.判断是内部账户还是外部账户的方法 四、消息调用和余

    2024年02月06日
    浏览(48)
  • Solidity基础六

    生活本来就是平凡琐碎的,哪有那么多惊天动地的大事,快乐的秘诀就是不管对大事小事都要保持热情 目录 一、Solidity的特殊变量(全局) 二、Solidity的不可变量 immutable的赋值方式  三、Solidity的事件与日志 事件和日志加深理解 四、Solidity的异常处理 1.require() 2.assert() 3.revert

    2024年02月09日
    浏览(42)
  • Solidity基础五

    暂时的一事无成也代表将来万事皆有可能! 目录 一、对Solidity文件的理解 二、Solidity的导sol文件(库、合约) 三、Solidity的继承 1.继承的分类 2.继承的可见性  3.父合约构造函数的传参 4.调用父合约成员 5.重写 四、Solidity的抽象合约 五、Solidity接口合约 实现接口 六、Solidit

    2024年02月08日
    浏览(42)
  • Solidity基础

    我们的学习方式是基于项目的,remix是我们写代码的地方.Remix - Ethereum IDE 在你的智能合约中你总是要做的第一件事情就是告诉Solidity,你正在使用哪个版本的solidity,并且加上SPDX许可。 接下来创建你的contract并为他命名(类似于其他语言的class) 第一个程序 每个合约都有一个

    2024年01月23日
    浏览(44)
  • Solidity基础八

    别慌,月亮也在大海某处迷茫  目录 一、Solidity 编程风格 1. 代码布局  2. 代码中各部分的顺序 3. 命名约定 二、Solidity 智能合约编写过程 1. solidity Hello World 2. 版本声明 3. 导入声明 4. 合约声明 三、Solidity 合约结构 智能合约 Test 四、Solidity 常见编译错误 五、Solidity 调用合约

    2024年02月07日
    浏览(58)
  • Solidity 基础(一)

    Solidity 官网 github Solidity是一种静态类型的花括号( curly-braces )编程语言,旨在开发运行在以太坊( Ethereum )上的智能合约。 Solidity正在迅速发展 作为一门相对年轻的语言,Solidity正在迅速发展。我们的目标是每月定期发布(非突破性)版本,每年大约发布一个突破性版本。您可以在

    2024年02月09日
    浏览(42)
  • Solidity 基础(二)语言描述-类型

    源文件可以包含任意数量的合约定义、import、pragma和using for指令以及struct、enum、function、error和constant variable定义。 如果智能合约的源代码可用,就可以更好地建立对智能合约的信任。由于提供源代码总是涉及到版权方面的法律问题,所以Solidity编译器鼓励使用机器可读的SP

    2024年02月06日
    浏览(36)
  • solidity(智能合约)零基础教学(3)

    前言:前面我们将了solidity的一些常用方法,接下来我们来讲一下,我们编写合约经常要用的一些功能; 一,modifier修饰符 在Solidity合约中,修饰符(modifier)是一种用于修改函数行为的特殊函数。通过使用修饰符,我们可以在执行函数之前、之后或中途对函数进行某些操作或

    2024年03月27日
    浏览(55)
  • solidity基础语法与简单案例20221130

    1、Todolist(日程表)练习 包括增删改查和使用地址获取结构体 2、事件event         是用于记录当前智能合约运行状态的方法,体现在区块链浏览器上以及交易记录的log,通过事件可以查询改变过的状态。         包括构建事件和触发事件。         事件是写入方法,不

    2024年02月05日
    浏览(34)
  • solidity基础(基于0.8.x)-HelloWord

    在线开发工具(remix): https://remix.ethereum.org 学习链接: 说明 链接 官方文档[最新](完整): https://docs.soliditylang.org/en/v0.8.17/index.html 官方文档[中文版]: https://learnblockchain.cn/docs/solidity/ solidity example(更助于理解): https://solidity-by-example.org/ solidity教程(简易,开发备忘手册

    2024年01月21日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包