加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

Ruby mixins:扩展和包含

发布时间:2020-12-16 20:38:20 所属栏目:百科 来源:网络整理
导读:我一直在阅读关于Ruby的mixin方法的几篇文章,扩展和包含,我仍然不太了解这个行为.我明白,扩展将把给定模块的实例方法作为单例方法添加到执行扩展的模块中,并且include将基本上将模块的内容(方法,常量,变量)附加到执行包含的模块的内容,有效地定义他们在接收
我一直在阅读关于Ruby的mixin方法的几篇文章,扩展和包含,我仍然不太了解这个行为.我明白,扩展将把给定模块的实例方法作为单例方法添加到执行扩展的模块中,并且include将基本上将模块的内容(方法,常量,变量)附加到执行包含的模块的内容,有效地定义他们在接收器.

然而,经过一番修补,试图了解行为将如何体现,我有几个问题.这是我的测试设置:

module Baz
  def blorg
    puts 'blorg'
  end
end

module Bar
  include Baz
  def blah
    puts 'blah'
  end
end

module Foo
  extend Bar
end

class Bacon
  extend Bar
end

class Egg
  include Bar
end

正如我所料,模块Bar获得了Baz(#blorg)中定义的实例方法,就像它们由于包含方法而被定义在本身,而Bacon类获得单一的方法Bacon :: blah和Bacon :: blorg通过扩展.

Bacon.blah  # => blah
Bacon.blorg # => blorg

而类Egg获得Bar(#blah和now #blorg)中定义的方法作为实例方法.

Egg.new.blah  # => blah
Egg.new.blorg # => blorg

我得到了所有这一切,这样做很好.

但是,我不明白使用#ancestors和#is_a的答案?方法.

Bacon.ancestors  # => [Bacon,Object,Kernel,BasicObject]
Bacon.is_a? Bar  # => true

Egg.ancestors    # => [Egg,Bar,Baz,BasicObject]
Egg.is_a? Bar    # => false

看起来扩展模块会导致#is_a?在查询该模块时返回true的方法,但不会添加到该类的祖先,反之亦然,包含:该类的祖先包含所包含的模块,但#is_a?查询时返回false.为什么会发生这种情况?

解决方法

不同之处在于,include将将include类添加到include类的祖先,而extend将会将扩展类添加到扩展类’singleton类的祖先中.唷.我们先来看看会发生什么:
Bacon.ancestors
#=> [Bacon,BasicObject]

Bacon.singleton_class.ancestors
#=> [Bar,Class,Module,BasicObject]

Bacon.new.singleton_class.ancestors
#=> [Bacon,BasicObject]

Bacon.is_a? Bar
#=> true

Bacon.new.is_a? Bar
#=> false

和蛋类

Egg.ancestors
#=> [Egg,BasicObject]

Egg.singleton_class.ancestors
#=> [Class,BasicObject]

Egg.new.singleton_class.ancestors
#=> [Egg,BasicObject]

Egg.is_a? Bar
#=> false

Egg.new.is_a? Bar
#=> true

那么什么foo.is_a? Klass实际上是检查foo.singleton_class.ancestors是否包含Klass.发生的另一件事是,当创建实例时,类的所有祖先成为实例的单例类的祖先.因此,对于任何类的所有新创建的实例,这将被评估为true:

Egg.ancestors == Egg.new.singleton_class.ancestors

那么这是什么意思?扩展和包含在不同级别上做同样的事情,希望以下示例使这一点清楚,因为扩展类的两种方法基本上是等效的:

module A
  def foobar
    puts 'foobar'
  end
end

class B
  extend A
end

class C
  class << self
    include A
  end
end

B.singleton_class.ancestors == C.singleton_class.ancestors
#=> true

其中class<自我只是奇怪的语法来到单身班.所以扩展真的只是一个简单的包括在单身阶级.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读