- 浏览: 624818 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
oldrat:
引用Special cases aren't special ...
武汉大学开源技术俱乐部 技术交流 第1期 -
yzsunlight:
试了试 ,不行
Android Studio SDK Manager无法正常下载如何设置 -
qianjigui:
更全面的文档:http://www.5wpc.info/it/ ...
Ruby正则表达式操作参考 -
qianjigui:
Anddy 写道Anddy 写道tag是自动创建的吗? 能手动 ...
vim的跳转 -
Anddy:
Anddy 写道tag是自动创建的吗? 能手动创建吗? 在sh ...
vim的跳转
最近在巩固Ruby 的基本语法知识,在这里把以前一些不知道的特性一一总结下来。
在Ruby中是允许method的重复声明的,并且在合适的时候还允许你去一个一个调用(利用super关键字)。
在这里通过几个实例,我将和大家分享一下Ruby的method查找路径和方式以及super的使用和参数问题。
首先,让大家来看看这样一个例子:
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
输出结果是:
"a 2"
method01.rb:7:in `a': super: no superclass method `a' (NoMethodError)
from method01.rb:13
shell returned 1
从结果中,我们可以发现:如果在一个class里面重复声明两个同样的方法(同样的method名称和参数数目 ),原先的方法将被后面的方法完全覆盖掉(即原先的定义无效了) 。当然这是一个很正常的状况,在Java中语法直接不允许。这里虽然允许了,但是没有什么实际上面的意义。那么这里的super是什么意义呢?让我们慢慢来看。
让我们看看第二个例子:
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
输出结果:
"a 2"
"B a 1"
"a 2 END"
似乎很怪异吧,这就是Ruby中super关键字的一部分作用了。其实有点像Java中的Method overwrite 然后在通过super.XXXMethod去调用祖先方法,其中执行的顺序也是类似的。例子中,我们也看到了那个原先定义在A中的a方法确实没有用了。
其实Module也有类似的效果:
module B def a p 'B a 1' end end class A include B def a p 'a 1' end def a p 'a 2' super p 'a 2 END' end end b = A.new b.a
输出结果同上面的那个Class-Class的例子:
"a 2"
"B a 1"
"a 2 END"
上面两个的层次关系其实也是method的查找顺序。好像Module和Class有同等效力,那么我们来将两个组合起来。
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
输出结果:
"a 2"
"M a 1"
"B a 1"
"M a END"
"a 2 END"
那么我们可以看到这个的层次结构了:
也即是说,如果同时出现了Module和祖先Class,那么程序将先到Module中寻找。那么如果祖先Class也含有这个Module又会是怎么样的状况呢?
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
输出结果:
"a 2"
"B a 1"
"M a 1"
"B a END"
"a 2 END"
如果将Module混入它的祖先,那么这个层次结构又发生了变化:
也就是说如果“老子”和“小子”都想有“XXX”,那么这个“XXX”肯定是归“老子”的了,毕竟“小子”得懂得孝道,不光中国是这样,在日本也是这样的文化吧。
下面我们来讨论一下,这个调用super是否把参数也传进去了呢?
在《Ruby For Rails》中有这样一段描述:
以super()调用,则不会传递caller的任何参数;
以super(a,b)调用,则将传递部分参数a、b.
我们仍然以一个例子来看看效果:
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)
输出结果:
"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"
果然,确实是有不同的效果。不过在使用super() 和super(a) 时,需要注意由于参数数据不全原方法需要是默认参数值的 。
最后,我给出一个综合的实例吧:
里面有很多错误和冗余,希望大家可以先自己看看输出结果然后再看实际结果,你们会有更多的收获的:
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
输出结果:
"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"
通过实例,大家应该可以比较清晰的了解method查找调用规律和具体的super使用了。
现在做以下总结:
- 同一个class和module中,重复声明一个method只有一个有效(用super也无法调用“过时”的几个);
- 一般过程是:本实例对象的方法体-->本对象对应类的方法体-->本对象包含的module(保证祖先那里没有include)-->祖先-(递归的)->......
- super传递参数有三种(裸词、空、部分)
- 不要写这种很难懂的方法结构
发表评论
-
Ruby 2.1 GC策略
2014-01-23 11:30 967对象管理主要涉及: Profiling support ... -
Ruby 动态特性鉴赏
2013-12-26 16:47 1337以下代码与代码学习来自<Ruby Best Prac ... -
Ruby: stack level too deep (SystemStackError)
2012-06-21 15:13 1220http://dalibornasevic.com/posts ... -
Ruby正则表达式操作参考
2012-02-02 10:03 3592在线测试工具: http://www ... -
Ruby二进制文件转码到Base64并通过Post进行提交
2011-02-08 07:28 1825ruby -v 写道 ruby 1.8.7 (2010-01 ... -
Ruby中的预定义变量
2010-12-10 07:00 1613原文地址 Predefined Variab ... -
在Ruby旧版本上进行升级
2009-05-18 15:51 7373由于ruby的内存泄漏很严重,我在网上也找到了不少资料,为了利 ... -
有根路由
2009-04-22 18:41 1078ActionController::Base.asset ... -
ROR常用正则表达式
2009-04-07 15:38 1145Valid email? Validate email add ... -
./script/generate salted_login.... Error
2009-03-30 11:31 1159错误信息 写道 ./script/ge ... -
ROR遗忘命令黑板
2009-02-11 11:22 1156对于安装了多个rails版本的情况,需要生成特定版本的rail ... -
Ruby 运算符小结
2009-02-07 23:54 9441个人感觉《Ruby程序设计语言》确实是一本好书,它将Ruby的 ... -
《Ruby程序设计语言》 第一章 学习笔记
2008-12-13 00:16 1010这一章是一个全面的基本的介绍。 Ruby是一个前大的动态语言, ... -
in_place_editing使用小记
2008-12-12 23:23 1235in_place_editing是一个用于原地编辑的ajax小 ... -
vim ruby
2008-12-04 22:43 2886http://www.g0574.com/viewthread ... -
ActiveRecord是什么&元编程简介
2008-11-30 00:07 1563回复:什么是ActiveRecord ActiveRecor ... -
Ruby中的block与变量作用域
2008-11-29 22:55 1106按照我们一般的思维模 ... -
Ruby的运算符!和数据类型Numbers小结
2008-11-18 16:07 1986这篇文章应该是承接 SSD06 Exercise02 个人解答 ... -
Ruby and Rails Development for Visual Studio
2008-10-09 18:04 1252我下了一个适用于VS2005的,欢迎大家下载使用。 ... -
Ruby 函数参数多余的空格和括号
2008-04-06 20:43 1792warning: parenthesize argumen ...
相关推荐
Ruby支持块(block),这是匿名函数的一种形式,通常与`yield`关键字一起使用。块可以用`do..end`或`{..}`定义,并且可以接受参数。 面向对象编程是Ruby的核心。Ruby中的每个对象都是一个类的实例,每个类都继承自`...
在Ruby中,可以通过在子类中定义同名方法并调用`super`关键字来实现。`super`关键字用于调用父类中的同名方法,这样可以在子类的方法中添加额外的功能,同时保留父类原有的功能。这种方式称为方法的组合,它允许我们...
- 函数与方法:Ruby中函数和方法是一体的,可以使用`def`定义,支持参数传递、默认参数、rest参数和block参数。 2. **面向对象编程** - 类与对象:Ruby是纯面向对象的语言,一切皆对象,通过`class`定义类,`new`...
- Proc和Lambda是Ruby中的匿名函数,它们可以捕获当前上下文,Proc更宽松,Lambda更严格,遵循函数调用规则。 5. **元编程** - Ruby的元编程能力强大,可以在运行时修改类和对象的行为。 - `class_eval`和`...
### Ruby的对象与方法调用 #### 一切皆对象 Ruby的一个核心特性是一切皆对象。这意味着无论是数字、字符串还是其他数据类型,在Ruby中都可以视为对象,并且可以调用它们的方法。例如: ```ruby (5.6).round # 输出 ...
Ruby中的类还可以继承,通过`操作符定义子类,并可以使用`super`关键字调用父类的方法。 三、控制结构 Ruby提供了多种控制结构,如条件语句(if/else, case)、循环(for, while, until, each)和流程控制语句...
Ruby中的函数定义使用`def`关键字,其语法与许多其他编程语言相似。函数可以接受参数,并且在函数体内部可以通过`return`语句返回值。例如,下面的代码展示了如何定义一个简单的函数`hello`,该函数接受一个参数`...
例如,在`Student`类中,`Person`作为其基类,`Student`必须调用`super`以执行`Person`的初始化过程。 #### 八、实例变量与类方法 实例变量以`@`开头,用于存储特定对象的状态。类方法则以`class 的形式定义,允许...
例如,`class MyClass`定义一个新类,`super`关键字用于调用父类的方法,`attr_accessor`则用于快速创建getter和setter方法。 2. **动态性**:Ruby允许在运行时改变对象的属性和行为。这通过其灵活的数据类型、变量...
Ruby支持动态方法定义和调用,以及元编程能力: ```ruby def MyClass.my_method puts "This is a dynamic method." end MyClass.my_method ``` **3.8 变量** - **局部变量**:作用域限制在定义它的方法内部。 -...
类可以继承其他类,使用`super`调用父类方法,以及实现多重继承和模块混合(Mix-in)。 5. **模块**:模块用于代码复用和分类,可以通过`include`或`prepend`引入到类中,提供命名空间隔离和防止命名冲突。 6. **...
Ruby中,类通过继承来扩展功能,可以使用`super`关键字调用父类的方法。同时,Ruby支持模块(Module),可以用来实现类似于JavaScript原型的混入(Mix-in)行为: ```ruby module Sayable def say_hello puts '...
super(*args) add_method(self, 'add', %w(in a), %w(in b)) add_method(self, 'div', %w(in a), %w(in b)) end end ``` 这里`add_method`的第一个参数是接收者(self),第二个参数是方法名,之后的参数分别...
3. **块(Blocks)和 Proc**:Ruby中的块是代码段,可以与方法一起使用,通过`do..end`或`{..}`定义。Proc是可存储的块,可以赋值给变量,作为参数传递或作为返回值。 4. **闭包(Closures)**:Ruby的Proc和Lambda...
- **super**:调用父类的同名方法。 **2.3 模块** - **模块定义**:使用 `module` 关键字定义模块。 - **混入模块**:通过 `include` 或 `extend` 将模块的功能添加到类或对象中。 **2.4 元编程** - **define_...
你可以使用`new`关键字实例化对象,`super`关键字调用父类的方法。 5. **模块(Module)** 模块是Ruby中实现代码重用的一种方式,可以包含常量、方法和类。通过`include`或`extend`,可以让一个类导入模块中的成员...
跳到super或在点处调用的构造函数 跳转到模块/类/常量定义 显示方法文档 显示有关使用ElDoc在点调用的方法的信息 方法和常量名称完成 使用简单的正则表达式搜索在当前文件中跳转和完成实例和本地变量名 要查看可用...
- **super关键字**:调用父类方法的机制。 #### 5. 类变量 - **类变量作用域**:一种特殊的变量类型,可在类的所有实例间共享。 ### 第五部分:数组 #### 1. 数组使用 - **数组创建**:创建数组的各种方式。 - **...
- `super` 调用父类的方法。 - `self` 引用当前对象自身。 4. **嵌入模块和块**: - `BEGIN` 和 `END` 用于在程序开始和结束时执行代码。 - `begin` 和 `end` 用于定义代码块。 5. **文件相关**: - `_FILE_`...