Ruby是一个真正的面向对象编程语言吗?

5

Ruby是一种完全面向对象的语言。在Ruby中,一切都是一个对象,因此属于某个类。例如,5属于Object类

1.9.3p194 :001 > 5.class
 => Fixnum 
1.9.3p194 :002 > 5.class.superclass
 => Integer 
1.9.3p194 :003 > 5.class.superclass.superclass
 => Numeric 
1.9.3p194 :005 > 5.class.superclass.superclass.superclass
 => Object 
1.9.3p194 :006 > 5.class.superclass.superclass.superclass.superclass
 => BasicObject 
1.9.3p194 :007 > 5.class.superclass.superclass.superclass.superclass.superclass
 => nil 

因此,我们必须通过在 Object_name#method_name 中添加类/对象名称来调用所有方法。例如:

5.times{|i| puts i}

现在,Rails有这些所谓的helpers,如stylesheet_link_tagjavascript_include_tagform_for等,它们遵循Object_name#method_name语法,所以我猜它们只是普通的函数。

因此,我的问题是:

  1. 这些Rails helpers是什么?
  2. 如果它们只是函数并且没有从任何类继承,那么这是否与声称在Ruby中“一切都是对象,没有基本类型”的说法相矛盾?例如,人们引用5.+(6)作为例子,说明甚至操作符也只是普通的方法?

1
当您看到没有明确接收者的方法调用时,则接收者为self。您是如何得出“一切都是对象”不成立的结论的? - Sergio Tulentsev
好的,我不知道self。我想我错了,谢谢! - CuriousMind
1
我会将此升级为答案 :) - Sergio Tulentsev
可能是如何理解Ruby完全面向对象?的重复问题。 - Peter Brown
3个回答

8
  • ActionView :: Helpers:该模块提供了许多helper方法,这些方法可用于视图模板中。例如,form_forlink_to 都是通过该模块提供的。
  • ActionController :: Helpers:该模块提供了许多helper方法,这些方法可在控制器中使用。例如,redirect_torender 都是通过该模块提供的。

对于没有接收者调用的其他内容,请查看Kernel模块,在其中定义了诸如puts之类的内容。由于该模块已包含在Object中,因此其方法在任何地方都可用。这究竟与“我个人认为过度使用”的所有内容都是对象的说法有何矛盾之处呢?


所以这些方法是在一个模块中定义的,而不是类?你的回答成为了我今天的“恍然大悟”时刻。有趣! - CuriousMind

5
这些Rails资产标签助手是ActionView的子模块,名为ActionView::Helpers::AssetTagHelper,提供了生成HTML的方法,将视图链接到像图片、JavaScript、样式表和Feed这样的资产。
由于模块的超类是,因此AssetTagHelpers也将具有它。
irb(main):016:0> ActionView::Helpers::AssetTagHelper
=> ActionView::Helpers::AssetTagHelper
irb(main):017:0> ActionView::Helpers::AssetTagHelper.class
=> Module
irb(main):018:0> ActionView::Helpers::AssetTagHelper.class.superclass
=> Object
irb(main):019:0> ActionView::Helpers::AssetTagHelper.class.superclass.superclass
=> BasicObject
irb(main):020:0> ActionView::Helpers::AssetTagHelper.class.superclass.superclass.superclass
=> nil

注意:为了简便起见,我只会专注于JavascriptIncludeTag,但它们都非常相似。

在这里,您将找到一个名为ActionView :: Helpers :: AssetTagHelper :: JavascriptIncludeTag的类。

您可以使用它进行实例化。

JavascriptIncludeTag.new(config, asset_paths) 

JavascriptIncludeTag类有一个名为asset_tag的方法,该方法调用了一个content_tag方法并返回正确的标记。
路径:/actionpack/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb
require 'action_view/helpers/asset_tag_helpers/asset_include_tag'

# NOTE: on the 'action_view/helpers/asset_tag_helpers/asset_include_tag' it requires '/actionpack/lib/action_view/helpers/tag_helper.rb' so now all this files are connected :)
.
.
.
def asset_tag(source, options)
  content_tag("script", "", { "src" => path_to_asset(source) }.merge(options))
end

路径:/actionpack/lib/action_view/helpers/tag_helper.rb
def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
  if block_given?
    options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
    content_tag_string(name, capture(&block), options, escape)
  else
    content_tag_string(name, content_or_options_with_block, options, escape)
  end
end

所以这大致是它们的工作方式。
注意:如果你觉得我的解释有点棘手,请告诉我,我会编辑并提供更好的解释。

4

当您看到没有显式接收器的方法调用时,接收器就是self。对象可以通过许多不同的方式获得方法。最明显的一种方式是您自己定义方法。然后您还可以包含模块。

class Person
  # this adds a bunch of methods to Person, making it a Mongoid model
  include Mongoid::Document
end

你包含的模块和继承的类可以以同样的方式获取功能。

所以,当你看到没有接收者的方法时,请考虑“此时的self是什么?它的类是什么?它定义了哪些方法?包含了哪些模块?”你会发现许多关于Ruby和Rails的有趣事情。:)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接