关于Ruby中的对象的问题

4

我正在阅读《Ruby元编程》

这是一本非常优秀的书。它涉及到了一些其他书籍没有提到的内容。

我有几个具体的问题,涉及到对象(我在前几章):

  1. 我知道RubyGems gem将方法'gem'安装到了模块Kernel中,以便该方法在每个对象上都可以使用。为什么它没有被放入Object类中呢?

  2. 他谈到了当Ruby查找方法时,它总是向右再向上查找。那么'up'到底是什么意思?我在图表中看到了它,只是我不太理解'up'的目的。作者没有对此进行解释。

  3. Object类的作用是什么?为什么这些方法不能直接放置在Class中?如果每个对象都属于一个类(即使它是Class),那么object、basicobject和kernel的作用是什么?

  4. String、Array等显然是Class的实例。而Class本身也是它自己的一个实例。既然Class是Class的实例......它怎么也能继承自Object呢?在代码的哪个部分涉及到了Class和Object的关系?

  5. 我知道kernel包含了一些可以在任何地方使用的方法,比如puts。这和问题1有关,但为什么不能将它们压缩到Object中呢......在那里似乎所有东西都继承自object?


我认为在尝试元编程之前,您需要尝试一本探索面向对象编程基础的书籍。有很多这样的书籍,快速搜索即可找到。 - ian
1
对于第3点:如果将这些方法放到Class上,它们将可用于Class的实例(如String、Array等),但不可用于Class的实例的实例(如String.new、Array.new等)。对于第4点:Class是Object的子类 Class.ancestors # => [Class, Module, Object, Kernel, BasicObject] - Joshua Cheek
@Iain:“有很多,快速搜索就能找到。”- 是使用Ruby作为编程语言的书籍,还是使用其他语言如Java和SmallTalk的书籍? - Andrew Grimm
如果你有兴趣使用Ruby,那就用Ruby吧。否则,任何面向对象的语言都可以,因为它们都会以类似的方式处理基础知识。不过我认为Ruby是一个特别好的选择,因为我认为它的面向对象设计做得很好,而且语法/风格不会妨碍学习。 - ian
@Iain:如果是这样的话,请推荐一些探索面向对象编程基础并使用Ruby作为编程语言的好书。 - Andrew Grimm
这可能是一个适合在Stack Programming板块提问的好问题,但我建议阅读Russ Olsen的任意一本书。这里有一份不一定是关于Ruby的面向对象编程书籍列表http://avdi.org/devblog/2011/12/16/oop-books/。虽然我没有阅读过其中的任何一本,但我读过这些作者的其他作品。 - ian
2个回答

2
  1. 两种方法都可以,但通常Object上的方法应该只处理特定的对象。将东西放在Kernel模块中更多地是全局性的,而不是关于对象。

  2. 我认为它的意思是“沿着继承链向上”。因此,它会在子类上查找方法,然后在该类的父类上查找,直到找到一个或没有父类为止。

  3. Object是所有对象的基类,自然地(至少对于Ruby 1.8而言)。疯狂的部分是类实际上是Class类的一个实例。(你明白吗?)所以向Class添加实例方法会向类对象添加方法,而不是这些类的实例。

  4. 几乎所有的Ruby都是一个对象。Class.superclass实际上是Module(类似于无法实例化的类),而Module.superclass返回Object。因此,如果Class类,则Class < Module < Object是继承链。(至少对于Ruby 1.8而言)

  5. 更多的惯例。由于Object可能会变得非常大,所以习惯于将事物放入模块中,然后稍后组合这些模块。如果方法不直接处理对象实例作为self,那么该方法就不应该直接属于Object。更全局的非对象实例方法(如gem)放在Kernel模块中,表示它们只是在任何地方可用的方法。


有关类对象和继承的更多信息...

class Foo < Bar
  def hi
    puts 'Hi!'
  end
end

这个代码非常棒。它定义了一个类对象。现在这个类对象被配置为有一个名字叫做Foo,一个父类Bar和一个方法hi。这些信息有点像这个类对象的元数据。
现在,类对象Foo本身是Class的一个实例。但是Foo定义了一个继承自Bar的类。Class类定义了一个数据结构来存储关于类的元数据。
你可以把Class类想象成被定义为这样:
class Class < Module

  # fictional method called on class creation
  def set_meta_data(name, superclass, methods)
    @name = name
    @superclass = superclass
    @methods = methods
  end

  # fictional way in which an instance might be created
  def new
    instance = Object.new
    instance.superclass = @superclass
    instance.addMethods(@methods)
    instance
  end
end

因此,一个类对象本身会继承自Class,但它会创建不继承的对象。

将类视为对象可能有点令人费解,但这也是 Ruby 的强大之处。


如果你无法实例化一个方法,那么为什么 x = Module.new 能够工作呢? - Tallboy
当你意识到 Class.new.new 的作用时,你就会明白它了 :) - Alex Wayne
哦,我明白了...那一定是一个没有命名的模块,如果你有一个叫做Hello的模块,你就不能使用Hello.new。 - Tallboy
因为Module.new会创建一个新模块。module Foo则会将Foo定义为Module类的实例。module Foo; end; Foo.new会导致错误,证明无法实例化_一个模块_(它本身是Module的一个实例),但你可以实例化Module(这是一个Class的实例)。 - Alex Wayne

1

对于1和5,伪关键字命令往往进入内核而不是对象。

对于2,子类相对于其父类“下降”是有意义的(子字面上意味着“在下方”)。因此,如果要访问父类及其祖先,则必须向“上”移动。

对于3,object对象不是Class的实例,它是Object的实例。

对于4,某物是Class的实例并从Object继承有什么问题吗?所有类都继承自Object。


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