- 浏览: 2075781 次
- 性别:
- 来自: NYC
文章分类
- 全部博客 (628)
- Linux (53)
- RubyOnRails (294)
- HTML (8)
- 手册指南 (5)
- Mysql (14)
- PHP (3)
- Rails 汇总 (13)
- 读书 (22)
- plugin 插件介绍与应用 (12)
- Flex (2)
- Ruby技巧 (7)
- Gem包介绍 (1)
- javascript Jquery ext prototype (21)
- IT生活 (6)
- 小工具 (4)
- PHP 部署 drupal (1)
- javascript Jquery sort plugin 插件 (2)
- iphone siri ios (1)
- Ruby On Rails (106)
- 编程概念 (1)
- Unit Test (4)
- Ruby 1.9 (24)
- rake (1)
- Postgresql (6)
- ruby (5)
- respond_to? (1)
- method_missing (1)
- git (8)
- Rspec (1)
- ios (1)
- jquery (1)
- Sinatra (1)
最新评论
-
dadadada2x:
user模型里加上 protected def email ...
流行的权限管理 gem devise的定制 -
Sev7en_jun:
shrekting 写道var pattern = /^(0| ...
强悍的ip格式 正则表达式验证 -
jiasanshou:
好文章!!!
RPM包rpmbuild SPEC文件深度说明 -
寻得乐中乐:
link_to其实就是个a标签,使用css控制,添加一个参数: ...
Rails在link_to中加参数 -
aiafei0001:
完全看不懂,不知所然.能表达清楚一点?
"$ is not defined" 的问题怎么办
Posted 3 days back at RailsTips.org - Home
In which I show the difference between include and extend when working with modules in Ruby.
Now that we know the difference between an instance method and a class method, let’s cover the difference between include and extend in regards to modules. Include is for adding methods to an instance of a class and extend is for adding class methods. Let’s take a look at a small example.
module Foo
def foo
puts 'heyyyyoooo!'
end
end
class Bar
include Foo
end
Bar.new.foo # heyyyyoooo!
Bar.foo # NoMethodError: undefined method ‘foo’ for Bar:Class
class Baz
extend Foo
end
Baz.foo # heyyyyoooo!
Baz.new.foo # NoMethodError: undefined method ‘foo’ for #<Baz:0x1e708>
As you can see, include makes the foo method available to an instance of a class and extend makes the foo method available to the class itself.
Include Example
If you want to see more examples of using include to share methods among models, you can read my article on how I added simple permissions to an app. The permissions module in that article is then included in a few models thus sharing the methods in it. That is all I’ll say here, so if you want to see more check out that article.
Extend Example
I’ve also got a simple example of using extend that I’ve plucked from the Twitter gem. Basically, Twitter supports two methods for authentication—httpauth and oauth. In order to share the maximum amount of code when using these two different authentication methods, I use a lot of delegation. Basically, the Twitter::Base class takes an instance of a “client”. A client is an instance of either Twitter::HTTPAuth or Twitter::OAuth.
Anytime a request is made from the Twitter::Base object, either get or post is called on the client. The Twitter::HTTPAuth client defines the get and post methods, but the Twitter::OAuth client does not. Twitter::OAuth is just a thin wrapper around the OAuth gem and the OAuth gem actually provides get and post methods on the access token, which automatically handles passing the OAuth information around with each request.
The implementation looks something like this (full file on github):
module Twitter
class OAuth
extend Forwardable
def_delegators :access_token, :get, :post
# a bunch of code removed for clarity
end
end
Rather than define get and post, I simply delegate the get and post instance methods to the access token, which already has them defined. I do that by extending the Forwardable module onto the Twitter::OAuth class and then using the def_delegators class method that it provides. This may not be the most clear example, but it was the first that came to mind so I hope it is understandable.
A Common Idiom
Even though include is for adding instance methods, a common idiom you’ll see in Ruby is to use include to append both class and instance methods. The reason for this is that include has a self.included hook you can use to modify the class that is including a module and, to my knowledge, extend does not have a hook. It’s highly debatable, but often used so I figured I would mention it. Let’s look at an example.
module Foo
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def bar
puts 'class method'
end
end
def foo
puts 'instance method'
end
end
class Baz
include Foo
end
Baz.bar # class method
Baz.new.foo # instance method
Baz.foo # NoMethodError: undefined method ‘foo’ for Baz:Class
Baz.new.bar # NoMethodError: undefined method ‘bar’ for #<Baz:0x1e3d4>
There are a ton of projects that use this idiom, including Rails, DataMapper, HTTParty, and HappyMapper. For example, when you use HTTParty, you do something like this.
class FetchyMcfetcherson
include HTTParty
end
FetchyMcfetcherson.get('http://foobar.com')
When you add the include to your class, HTTParty appends class methods, such as get, post, put, delete, base_uri, default_options and format. I think this idiom is what causes a lot of confusion in the include verse extend understanding. Because you are using include it seems like the HTTParty methods would be added to an instance of the FetchyMcfetcherson class, but they are actually added to the class itself.
Conclusion
Hope this helps those struggling with include verse extend. Use include for instance methods and extend for class methods. Also, it is sometimes ok to use include to add both instance and class methods. Both are really handy and allow for a great amount of code reuse. They also allow you to avoid deep inheritance, and instead just modularize code and include it where needed, which is much more the ruby way.
发表评论
-
Destroying a Postgres DB on Heroku
2013-04-24 10:58 935heroku pg:reset DATABASE -
VIM ctags setup ack
2012-04-17 22:13 3259reference ctags --extra=+f --e ... -
alias_method_chain方法在3.1以后的替代使用方式
2012-02-04 02:14 3295alias_method_chain() 是rails里的一个 ... -
一些快速解决的问题
2012-01-19 12:35 1472问题如下: 引用Could not open library ... -
API service 安全问题
2011-12-04 08:47 1386这是一个长期关注的课题 rest api Service的 ... -
Module方法调用好不好
2011-11-20 01:58 1349以前说,用module给class加singleton方法,和 ... -
一个ajax和rails交互的例子
2011-11-19 01:53 1908首先,这里用了一个,query信息解析的包,如下 https: ... -
Rails 返回hash给javascript
2011-11-19 01:43 2277这是一个特别的,不太正统的需求, 因为,大部分时候,ajax的 ... -
关于Rubymine
2011-11-18 23:21 2267开个帖子收集有关使用上的问题 前一段时间,看到半价就买了。想 ... -
ruby中和javascript中,动态方法的创建
2011-11-18 21:01 1241class Klass def hello(*args) ... -
textmate快捷键 汇总
2011-11-16 07:20 8147TextMate 列编辑模式 按住 Alt 键,用鼠标选择要 ... -
Ruby面试系列六,面试继续面试
2011-11-15 05:55 2025刚才受到打击了,充分报漏了自己基础不扎实,不肯向虎炮等兄弟学习 ... -
说说sharding
2011-11-13 00:53 1492这个东西一面试就有人 ... -
rails面试碎碎念
2011-11-12 23:51 1946面试继续面试 又有问ru ... -
最通常的git push reject 和non-fast forward是因为
2011-11-12 23:29 17216git push To git@github.com:use ... -
Rails 自身的many to many关系 self has_many
2011-11-12 01:43 2737简单点的 #注意外键在person上people: id ... -
Rails 3下的 in place editor edit in place
2011-11-12 01:20 946第一个版本 http://code.google.com/p ... -
Heroku 的诡异问题集合
2011-11-11 07:22 1697开个Post记录,在用heroku过程中的一些诡异问题和要注意 ... -
SCSS 和 SASS 和 HAML 和CoffeeScript
2011-11-07 07:52 12960Asset Pipeline 提供了内建 ... -
Invalid gemspec because of the date format in specification
2011-11-07 02:14 2122又是这个date format的错误。 上次出错忘了,记录下 ...
相关推荐
在Ruby on Rails中,`include`和`extend`是用来引入模块到类或对象中的关键语法,它们可以帮助我们更好地组织和重用代码。这两个关键字的主要区别在于它们如何将模块中的方法添加到目标类或对象。 首先,`include`...
### 模块的力量:Ruby中include与extend的深度解析 #### Ruby语言简介 Ruby是一种高级、面向对象的编程语言,自1995年由日本开发者松本行弘(Yukihiro "Matz" Matsumoto)创建以来,一直受到广泛的欢迎。它的设计...
### Ruby中require、load、include、extend的区别介绍 在Ruby编程语言中,为了实现代码的重用和组织,开发者经常需要引入外部文件或模块。在这一过程中,`require`、`load`、`include`、`extend`这几个关键字发挥了...
- 使用`include`将模块的成员导入到类中,`extend`将模块的方法添加到对象实例上。 6. **异常处理** - `begin-rescue-end`用于捕获和处理异常。 - `raise`用于引发异常,`ensure`确保在任何情况下执行的代码。 ...
10. **模块与命名空间**:模块用于组织代码,提供命名空间,防止命名冲突,并可通过`include`或`extend`引入模块的方法。 通过阅读"Ruby经典"这本书,读者将逐步了解并掌握以上知识点,从而在Ruby编程世界中...
了解如何创建自定义类,继承和模块混入(include/extend)是基础。 - 类变量和实例变量的区别,以及`class 语法来改变当前类的上下文也是重要的知识点。 5. **异常处理**: - `begin...rescue...end`结构用于捕获...
`include`和`extend`关键字分别用于实例方法和类方法的混入。 6. **常量、变量和符号**:Ruby的常量、局部变量和符号在运行时也可以被查询和修改,尽管常量的修改可能会导致警告。 7. **Closures和Proc对象**:...
模块通过`module`关键字定义,使用`include`或`extend`导入到其他类或对象中: ```ruby module MathOperations def add(a, b) a + b end end class Calculator include MathOperations end calc = Calculator...
- 源代码中会展示如何使用`include`和`extend`关键字引入模块。 4. **异常处理** - `begin-rescue-end`结构用于处理程序运行时可能出现的错误,源代码会演示如何捕获和处理异常。 5. **集合操作** - 集合操作如...
5. **模块和混合**:模块是命名空间的容器,用于组织类和方法,还可以通过`include`或`extend`实现代码复用和混入。 6. **数据结构**:Ruby提供了丰富的内置数据结构,如数组(Array)和哈希(Hash)。数组是有序的...
- 模块用于代码组织和命名空间隔离,可以使用`include`、`extend`引入模块功能。 5. **继承与多态**: - Ruby支持单继承,但通过模块混入可以实现多重继承的效果。 - 多态性通过方法重写和消息转发实现。 6. **...
7. **模块(Module)**: 模块用于封装代码,提供命名空间,并可以通过`include`或`extend`引入到类中。 8. **异常处理**: Ruby使用`begin..rescue..else..ensure`来处理异常。例如: ```ruby begin # 可能会抛出...
3. 模块混入:Ruby中的模块可以被包含(include)到类中,这在本质上是把模块中的方法和类混合,从而增强类的功能。这里涉及到的还有模块的内联扩展。 4. 代码块(Blocks)、迭代器(Iterators)和Procs:它们是...
在Ruby编程语言中,`module_function`和`extend self`都是与模块(module)相关的特性,它们用于控制方法的可见性和行为。理解这两者的异同对于编写清晰、可维护的代码至关重要。 首先,我们来看`module_function`...
10. **模块混合**:Ruby的模块可以被类“混入”(include或extend),实现跨类的代码共享。 11. **类和对象初始化**:Ruby中通过initialize方法初始化对象,而Class.new可以用来创建新的类。 12. **Ruby on Rails*...
- 模块(Module)用于封装功能,可以使用`include`将模块的方法添加到类的实例方法中,使用`extend`将模块的方法添加到类本身(类方法)。 - `load`用于加载文件,如果已经加载过,不会再次加载。 8. `case`语句 ...
7. **mixin**:在Ruby中,模块(Module)可以用来实现代码复用,通过`include`或`extend`关键字,模块可以被混入类中,提供类的方法和常量,这是Ruby实现多重继承的一种方式。 8. **ruby mix-in**:进一步探讨了...
通过`include`或`extend`关键字,一个类可以使用模块中的方法。 6. **异常处理** 使用`begin/rescue/ensure/else`块处理程序中的错误。Ruby提供了多种内置异常类,如`StandardError`、`RuntimeError`等。 7. **...