为什么可以';我不能从ruby中的类方法调用include吗?
您可以在ruby中调用include来混入具有类的模块,但必须在类定义的开头进行。为什么不能在类函数中完成?有其他语法吗 例: ^^这是可行的,但如果我将IncludeTester更改为以下内容,则会出现错误“undefined method`include'”为什么可以';我不能从ruby中的类方法调用include吗?,ruby,Ruby,您可以在ruby中调用include来混入具有类的模块,但必须在类定义的开头进行。为什么不能在类函数中完成?有其他语法吗 例: ^^这是可行的,但如果我将IncludeTester更改为以下内容,则会出现错误“undefined method`include'” 实际上完全可以从类方法中包含模块,如下所示: module Stuff def say_hello puts "hello" end end class Foo def self.i_am_a_class_meth
实际上完全可以从类方法中包含模块,如下所示:
module Stuff
def say_hello
puts "hello"
end
end
class Foo
def self.i_am_a_class_method
include Stuff
end
def i_am_an_instance_method
end
end
但是,不能从实例方法中执行此操作,因为只能作为私有类方法使用,因此不能从Foo.new实例中访问。实际上完全可以从类方法中包含模块,如下所示:
module Stuff
def say_hello
puts "hello"
end
end
class Foo
def self.i_am_a_class_method
include Stuff
end
def i_am_an_instance_method
end
end
但是,您不能从实例方法执行此操作,因为只能作为私有类方法使用,因此无法从Foo.new实例访问。是来自模块的方法,模块是类的超类,因此include
是类上的方法,这使它成为IncludeTester中的类方法。执行此操作时:
class IncludeTester
def initialize
include UsefulThings
end
end
class IncludeTester
include UsefulThings
end
您试图在一个实例方法中调用一个类方法,Ruby说
`初始化“:未定义的方法“include”
class IncludeTester
def initialize
include UsefulThings
end
end
因为没有名为include
的实例方法。如果要在实例方法(例如初始化
)内调用类方法,请执行以下操作:
def initialize
self.class.include UsefulThings
end
但这是行不通的,因为include
是一个私有方法;不过,您可以通过以下方式解决此问题:
每次实例化IncludeTester
时,您都会执行includeUsefilThings
,除了没有多大意义之外,如果UsefilThings
有一个方法,它可能会导致问题。是模块中的一个方法,模块是类的超类,因此include
是类上的一个方法,这使它成为IncludeTester中的类方法。执行此操作时:
class IncludeTester
def initialize
include UsefulThings
end
end
class IncludeTester
include UsefulThings
end
您试图在一个实例方法中调用一个类方法,Ruby说
`初始化“:未定义的方法“include”
class IncludeTester
def initialize
include UsefulThings
end
end
因为没有名为include
的实例方法。如果要在实例方法(例如初始化
)内调用类方法,请执行以下操作:
def initialize
self.class.include UsefulThings
end
但这是行不通的,因为include
是一个私有方法;不过,您可以通过以下方式解决此问题:
每次实例化
IncludeTester
时,您都会执行includeUsefilThings
,除了没有多大意义之外,如果UsefilThings
有一个方法,它可能会导致问题。您想要扩展
方法:
class IncludeTester
def initialize
extend UsefulThings
end
end
这也不需要在a方法中完成:
IncludeTester.new.tap { |newTester| newTester.extend(UsefulThings) }
您需要
extend
方法:
class IncludeTester
def initialize
extend UsefulThings
end
end
这也不需要在a方法中完成:
IncludeTester.new.tap { |newTester| newTester.extend(UsefulThings) }
它可以在类方法中完成
这项工作:
module UsefulThings
def a
puts "a"
end
end
class IncludeTester
def self.mix_in_useful_things
include UsefulThings
end
end
x = IncludeTester.new
IncludeTester.mix_in_useful_things
x.a # => a
但“initialize”不是类方法,而是实例方法
“new”是一个类方法。您可以将new视为分配一个新对象,然后对其调用initialize,将传递给new的参数传递给initialize
不能在initialize中直接调用include,因为include是类的私有方法(从模块继承),而不是新创建的IncludeTester实例的私有方法
如果要从实例方法将模块包含到类中,必须执行以下操作:
class IncludeTester
def initialize
self.class.send(:include, UsefulThings)
end
end
这里有必要使用“send”,因为include是私有方法,这意味着它只能通过隐式接收方(self)直接调用
当您在类定义中正常调用initialize时,实际上是使用“self”的隐式接收器调用它,它指的是正在定义的类
这就是当你这样做时实际发生的情况:
class IncludeTester
def initialize
include UsefulThings
end
end
class IncludeTester
include UsefulThings
end
它可以在类方法中完成
这项工作:
module UsefulThings
def a
puts "a"
end
end
class IncludeTester
def self.mix_in_useful_things
include UsefulThings
end
end
x = IncludeTester.new
IncludeTester.mix_in_useful_things
x.a # => a
但“initialize”不是类方法,而是实例方法
“new”是一个类方法。您可以将new视为分配一个新对象,然后对其调用initialize,将传递给new的参数传递给initialize
不能在initialize中直接调用include,因为include是类的私有方法(从模块继承),而不是新创建的IncludeTester实例的私有方法
如果要从实例方法将模块包含到类中,必须执行以下操作:
class IncludeTester
def initialize
self.class.send(:include, UsefulThings)
end
end
这里有必要使用“send”,因为include是私有方法,这意味着它只能通过隐式接收方(self)直接调用
当您在类定义中正常调用initialize时,实际上是使用“self”的隐式接收器调用它,它指的是正在定义的类
这就是当你这样做时实际发生的情况:
class IncludeTester
def initialize
include UsefulThings
end
end
class IncludeTester
include UsefulThings
end
是的,这非常有帮助(其他答案也是如此)。是的,这非常有帮助(其他答案也是如此)。差不多!从实例方法调用“extend”不会将模块混合到实例的类中——它会导致将一个不可见的“ghost”类添加到对象继承链的开头(在实际类之前),并将模块混合到该继承链中。像这样混合模块不会影响同一类的其他对象。几乎!从实例方法调用“extend”不会将模块混合到实例的类中——它会导致将一个不可见的“ghost”类添加到对象继承链的开头(在实际类之前),并将模块混合到该继承链中。这样混合模块不会影响同一类的其他对象。绕过私有方法访问保护的惯用方法是使用
send
,而不是任何eval
方法。绕过私有方法访问保护的惯用方法是使用send
,不是任何eval
方法。