zoukankan      html  css  js  c++  java
  • ruby-super用法

    ruby语法-super用法

    本文主要介绍ruby中super方法的使用、super方法参数传递、method执行顺序。


    下面主要通过实例来说明super方法的使用:

    示例1:

    #!/usr/bin/env ruby
    class A
      def a
        p 'a 1'
      end
      def a
        p 'a 2'
        super
        p 'a 2 END'
      end
    end
    
    b = A.new
    b.a
    

    示例1输出:

    ➜  tmp ./test.rb
    "a 2"
    ./test.rb:9:in `a': super: no superclass method `a' for #<A:0x007fac830b0dd8> (NoMethodError)
    	from ./test.rb:15:in `<main>'
    

    示例1说明:

    可以看出,当一个类里面定义了多个相同名称的函数时,后面的会完全覆盖前面的,即前面的方法等于无效。
    "a"函数被重新定义后调用了"super"方法报错了。报错信息大致意思是:找不到superclass内的方法"a"。那么是不是使用super方法需要另外一个类呢?
    

    示例2:

    #!/usr/bin/env ruby
    class B
      def a
        p 'B a 1'
      end
    end
    
    class A < B
      def a
        p 'a 1'
      end
      def a
        p 'a 2'
        super
        p 'a 2 END'
      end
    end
    
    b = A.new
    b.a
    

    示例2输出:

    ➜  tmp ./test.rb
    "a 2"
    "B a 1"
    "a 2 END"
    

    示例2说明:

    • 类A内后面的a函数确实覆盖了前面的。
    • super方法的使用也可以直观的体现出来了,当调用super方法时,类A会自动调用父类B中的"a"方法,然后再回到类A继续执行。

    示例2类的调用顺序:

    A->B
    

    示例3:

    #!/usr/bin/env ruby
    module M
      def a
        p 'M a 1'
      end
    end
    
    class A
      include M
      def a
        p 'a 1'
      end
      def a
        p 'a 2'
        super
        p 'a 2 END'
      end
    end
    
    b = A.new
    b.a
    

    示例3输出:

    ➜  tmp ./test.rb
    "a 2"
    "M a 1"
    "a 2 END"
    

    示例3说明

    module和class的继承有同样的效果。
    

    示例3类的执行顺序

    A->M
    

    示例4:
    当A类既继承module M又继承类B会怎么样呢?

    #!/usr/bin/env ruby
    class B
      def a
        p 'B a 1'
      end
    end
    
    module M
      def a
        p 'M a 1'
        super
        p 'M a END'
      end
    end
    
    class A < B
      include M
      def a
        p 'a 1'
      end
      def a
        p 'a 2'
        super
        p 'a 2 END'
      end
    end
    
    b = A.new
    b.a
    

    示例4输出:

    ➜  tmp ./test.rb
    "a 2"
    "M a 1"
    "B a 1"
    "M a END"
    "a 2 END"
    

    实例4说明:

    如果同时出现了Module和祖先Class,那么程序将先到Module中寻找,然后再到父类中寻找。
    

    示例4类的调用顺序

    A->M->B
    

    示例5:
    那么当父类里面也使用super调用了M模块会怎么样呢?

    #!/usr/bin/env ruby
    module M
      def a
        p 'M a 1'
      end
    end
    
    class B
      def a
        p 'B a 1'
        super
        p 'B a END'
      end
      include M
    end
    
    class A < B
      include M
      def a
        p 'a 1'
      end
      def a
        p 'a 2'
        super
        p 'a 2 END'
      end
    end
    
    b = A.new
    b.a
    

    示例5输出:

    ➜  tmp ./test.rb
    "a 2"
    "B a 1"
    "M a 1"
    "B a END"
    "a 2 END"
    

    示例5说明:

    当父类和子类都使用super方法调用了模块M,那么会现执行父类的调用,子类的调用作废。
    也就是说如果“老子”和“小子”都想有“XXX”,那么这个“XXX”肯定是归“老子”的了,毕竟“小子”得懂得孝道,不光中国是这样,在日本也是这样的文化吧。
    

    示例5类的调用顺序:

    A->B->M
    

    示例6:
    以上示例说明了super方法的使用和类的调用顺序,下面介绍下super方法的参数传递,直接上示例:

    #!/usr/bin/env ruby
    module M
      def a(x=5,y=6)
        p 'M a 1'
        p x
        p y
      end
    end
    
    class B
      def a(x=3,y=4)
        p 'B a 1'
        p x
        p y
        super(x)
        p 'B a END'
      end
      include M
    end
    
    class A < B
      include M
      def a
        p 'a 1'
      end
      def a(x=1,y=2)
        p 'a 2'
        p x
        p y
        super
        p 'a 2 END'
        super()
      end
    end
    
    b = A.new
    b.a(-1,-2)
    

    示例6输出:

    ➜  tmp ./test.rb
    "a 2"
    -1
    -2
    "B a 1"
    -1
    -2
    "M a 1"
    -1
    6
    "B a END"
    "a 2 END"
    "B a 1"
    3
    4
    "M a 1"
    3
    6
    "B a END"
    

    示例6说明:

    类A使用的super函数,类A的x和y的值全部传递给了B.a;
    然后类B使用的super(x),B的x值传递给了模块M;
    类A使用的super()函数时,类A的x和y的值都不传递给类;
    

    super方法参数传递:

    • 以裸词super调用祖先/模块方法(callee),则将传递调用者(caller)的全部方法参数;
    • 以super()调用,则不会传递caller的任何参数;
    • 以super(a,b)调用,则将传递部分参数a、b

    示例7:
    综合的示例,如果能看懂这个示例那么说明你对super方法有了一定的了解:

    #!/usr/bin/env ruby
    module M
      def report( a = 4, b =5)
        p "M report begin: a=#{a},b=#{b}"
        a = 6
        super(a)
        p "M report end"
      end
    end
    
    class B
      def report(a=11,b=12)
        p "B report 1 begin: a=#{a},b=#{b}"
        p "B report 1 end"
      end
      def report(a=13,b=14)
        p "B report 2 begin: a=#{a},b=#{b}"
        #super
        p "B report 2 end"
      end
    end
    
    class C < B
      def report( a=8,b=9)
        p "C report 1 begin: a=#{a},b=#{b}"
        p "C report 1 end"
      end
      def report( a=7,b=3)
        p "C report 2 begin: a =#{a},b=#{b}"
        super()
        p "C report 2 End"
      end
      include M
    end
    
    class D < C
      def report( a = 2, b=1)
        p "D report 1 begin: a=#{a},b=#{b}"
        super(a,b)
        p "D report 1 end"
      end
      include M
      def report(a = -2, b=-1)
        p "D report 2 begin: a=#{a},b=#{b}"
        super
        p "D report 2 end"
      end
    end
    
    d = D.new
    d.report
    

    示例7输出:

    ➜  tmp ./test.rb
    "D report 2 begin: a=-2,b=-1"
    "C report 2 begin: a =-2,b=-1"
    "M report begin: a=4,b=5"
    "B report 2 begin: a=6,b=14"
    "B report 2 end"
    "M report end"
    "C report 2 End"
    "D report 2 end"
    

    总结

    • 同一个class和module中, 如果定义了多个相同的方法,那么后面的方法会完全覆盖前面的方法,前面的方法作废。
    • 使用super函数时方法的调用顺序为:本实例对象的方法-->被继承的module的方法-->父类的方法-->递归的-->...... (当父类和子类同时使用super方法调用了相同的模块,那么父类的调用生效,子类不生效)
    • super的参数传递分为三种:裸词(全部传递)、空(全部不传递)、部分(部分参数传递)

    参考文档:
    http://www.iteye.com/topic/273704

  • 相关阅读:
    easyexcel: The maximum length of cell contents (text) is 32,767 characters
    分库分表情况下添加索引
    如何保证消息顺序执行(Rabbitmq/kafka)
    MySQL Boolean类型的坑
    Redis居然还有比RDB和AOF更强大的持久化方式?
    ThreadLocal的应用场景和注意事项有哪些?
    spring boot 设置tomcat post参数限制
    并发慎用——System.currentTimeMillis()
    Java多线程中static变量的使用
    临时修改session日期格式冲突问题
  • 原文地址:https://www.cnblogs.com/mauricewei/p/8596070.html
Copyright © 2011-2022 走看看