当前位置:  开发笔记 > 后端 > 正文

Ruby中包含和扩展有什么区别?

如何解决《Ruby中包含和扩展有什么区别?》经验,为你挑选了3个好方法。

刚刚开始关注Ruby元编程.mixin/modules总是让我困惑.

include:将指定模块方法中的混合作为目标类中的实例方法

extend:将指定的模块方法混合为目标类中的类方法

那么主要区别在于这还是潜伏着更大的龙? 例如

module ReusableModule
  def module_method
    puts "Module Method: Hi there!"
  end
end

class ClassThatIncludes
  include ReusableModule
end
class ClassThatExtends
  extend ReusableModule
end

puts "Include"
ClassThatIncludes.new.module_method       # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method            # "Module Method: Hi there!"

John Douthat.. 310

extend - 将指定模块的方法和常量添加到目标的元类(即单例类),例如

如果你打电话Klazz.extend(Mod),现在Klazz有Mod的方法(作为类方法)

如果你调用obj.extend(Mod),现在obj有Mod的方法(作为实例方法),但没有其他实例obj.class添加了这些方法.

extend 是一种公共方法

include - 默认情况下,它将指定模块的方法混合为目标模块/类中的实例方法.例如

如果你打电话class Klazz; include Mod; end;,现在Klazz的所有实例都可以访问Mod的方法(作为实例方法)

include 是一个私有方法,因为它旨在从容器类/模块中调用.

但是,模块经常通过修补方法来覆盖其 include行为included.这在传统的Rails代码中非常突出.来自Yehuda Katz的更多细节.

include假设您运行以下代码,有关其默认行为的更多详细信息

class Klazz
  include Mod
end

如果Mod已包含在Klazz或其祖先之一中,则include语句无效

它还包括Mod在Klazz中的常量,只要它们不冲突

它使Klazz可以访问Mod的模块变量,例如@@foo@@bar

如果存在循环包含则引发ArgumentError

将模块作为调用者的直接祖先附加(即它将Mod添加到Klazz.ancestors,但是Mod没有添加到Klazz.superclass.superclass.superclass的链中.因此,调用superKlazz #foo将在检查之前检查Mod#foo Klazz的真正超类的foo方法.有关详细信息,请参阅RubySpec.).

当然,ruby核心文档总是最适合这些事情的地方.RubySpec项目也是一个很棒的资源,因为他们精确地记录了这些功能.

#include RubySpec rubydoc

#included RubySpec rubydoc

#extend RubySpec rubydoc

#extended RubySpec rubydoc

#extend_object RubySpec rubydoc

#append_features RubySpec rubydoc

我知道这是一个相当古老的帖子,但回复的清晰度不能阻止我评论.非常感谢您的解释. (18认同)


domgblackwel.. 240

你所说的是对的.然而,除此之外还有更多.

如果你有一个类Klazz和模块Mod,包括Modin Klazz给出了Klazz访问Mod方法的实例.或者你可以Klazz通过Mod赋予 Klazz访问Mod方法来扩展.但是你也可以扩展一个任意对象o.extend Mod.在这种情况下,单个对象获取Mod方法,即使具有相同类的所有其他对象o也没有.



1> John Douthat..:

extend - 将指定模块的方法和常量添加到目标的元类(即单例类),例如

如果你打电话Klazz.extend(Mod),现在Klazz有Mod的方法(作为类方法)

如果你调用obj.extend(Mod),现在obj有Mod的方法(作为实例方法),但没有其他实例obj.class添加了这些方法.

extend 是一种公共方法

include - 默认情况下,它将指定模块的方法混合为目标模块/类中的实例方法.例如

如果你打电话class Klazz; include Mod; end;,现在Klazz的所有实例都可以访问Mod的方法(作为实例方法)

include 是一个私有方法,因为它旨在从容器类/模块中调用.

但是,模块经常通过修补方法来覆盖其 include行为included.这在传统的Rails代码中非常突出.来自Yehuda Katz的更多细节.

include假设您运行以下代码,有关其默认行为的更多详细信息

class Klazz
  include Mod
end

如果Mod已包含在Klazz或其祖先之一中,则include语句无效

它还包括Mod在Klazz中的常量,只要它们不冲突

它使Klazz可以访问Mod的模块变量,例如@@foo@@bar

如果存在循环包含则引发ArgumentError

将模块作为调用者的直接祖先附加(即它将Mod添加到Klazz.ancestors,但是Mod没有添加到Klazz.superclass.superclass.superclass的链中.因此,调用superKlazz #foo将在检查之前检查Mod#foo Klazz的真正超类的foo方法.有关详细信息,请参阅RubySpec.).

当然,ruby核心文档总是最适合这些事情的地方.RubySpec项目也是一个很棒的资源,因为他们精确地记录了这些功能.

#include RubySpec rubydoc

#included RubySpec rubydoc

#extend RubySpec rubydoc

#extended RubySpec rubydoc

#extend_object RubySpec rubydoc

#append_features RubySpec rubydoc


我知道这是一个相当古老的帖子,但回复的清晰度不能阻止我评论.非常感谢您的解释.

2> domgblackwel..:

你所说的是对的.然而,除此之外还有更多.

如果你有一个类Klazz和模块Mod,包括Modin Klazz给出了Klazz访问Mod方法的实例.或者你可以Klazz通过Mod赋予 Klazz访问Mod方法来扩展.但是你也可以扩展一个任意对象o.extend Mod.在这种情况下,单个对象获取Mod方法,即使具有相同类的所有其他对象o也没有.



3> Toby Hede..:

那是对的.

在幕后,include实际上是append_features的别名,(来自文档):

Ruby的默认实现是将此模块的常量,方法和模块变量添加到aModule(如果此模块尚未添加到aModule或其祖先之一).

推荐阅读
mobiledu2402851173
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有