它等同于在主环境中定义方法:
def foo; end
并将其定义为Object
的实例方法:
class Object
def foo; end
end
还是有办法区分它们吗?
答案 0 :(得分:2)
当你没有指定一个对象的单身类时,应该定义方法,即当你不说
时def bar.foo; end
但只是
def foo; end
然后该方法在所谓的default definee中定义。通常,默认的definee是词汇封闭的module
,但在顶层,Object
和默认情况下方法变为private
。 (默认的definee也可以通过各种元编程方法来改变。)
因此,您发布的两个代码段不等于,因为第一个会定义private
方法,第二个会定义public
方法:
def foo; end
method(:foo).owner
# => Object
Object.private_instance_methods(false).include?(:foo)
# => true
但是
class Object; def foo; end end
method(:foo).owner
# => Object
Object.private_instance_methods(false).include?(:foo)
# => false
请注意,在IRb和其他一些REPL中,顶级方法最终可能会public
。这是一个众所周知的不兼容性,泄露了这些REPL的私有内部实现细节,并且不是 Ruby语义的官方部分。
答案 1 :(得分:1)
对于我运行一些测试,我看到在main
的上下文中定义的方法被设置为private_instance_methods
而不是Object
的{{1}}。这意味着除非您在public_methods
上专门定义私有实例方法,否则您应该能够区分它们。
奇怪的是我无法确认其他帖子显示这些是Object的公共方法。如果有人对此有任何见解,我很乐意理解。 (也许它与使用Object
?)
我在1.9.3,2.0.0,2.1.5和2.2.3中也是如此,所以我不确定为什么其他人会得到不同的答案。
<强> /scripts/test.rb 强>
pry
(原始输出):
ruby 1.9.3p551(2014-11-13)[i386-mingw32]
puts "RUBY_VERSION: #{RUBY_VERSION}"
puts 'def foo; "in Main";end'
def foo; "in Main";end
puts "foo method response: #{foo}"
puts "Object.private_instance_methods:#{Object.private_instance_methods(false).inspect}"
puts "Trying to call Object.new.foo"
Object.new.foo
ruby 2.0.0p247(2013-06-27)[x64-mingw32]
RUBY_VERSION: 1.9.3
def foo; "in Main";end
foo method response: in Main
Object.private_instance_methods:[:foo]
Trying to call Object.new.foo
/scripts/test.rb:7:in `<main>': private method `foo' called for #<Object:0x640368> (NoMethodError)
ruby 2.1.5p273(2014-11-13修订版48405)[i386-mingw32]
RUBY_VERSION: 2.0.0
def foo; "in Main";end
foo method response: in Main
Object.private_instance_methods:[:foo]
Trying to call Object.new.foo
/scripts/test.rb:7:in `<main>': private method `foo' called for #<Object:0x00000002d34b98> (NoMethodError)
ruby 2.2.3p173(2015-08-18修订版51636)[i386-mingw32]
RUBY_VERSION: 2.1.5
def foo; "in Main";end
foo method response: in Main
Object.private_instance_methods:[:foo]
Trying to call Object.new.foo
/scripts/test.rb:7:in `<main>': private method `foo' called for #<Object:0x2bec750> (NoMethodError)
答案 2 :(得分:0)
Ruby 2.2.1。
self
#=> main
self == Object
#=> false
Object === self
#=> true
所以main
是Object
的一个实例。
main
不等于Object
- 这些是不同的事情。
main
和Object
def foo; end
self.class.instance_methods(false)
#=> [:pry, :__binding__, :foo]
class Object
def bar; end
end
#=> :bar
self.class.instance_methods(false)
#=> [:pry, :__binding__, :foo, :bar]
可用于main
和Object
的新实例:
foo
#=> nil
bar
#=> nil
Object.new.foo
#=> nil
Object.new.bar
#=> nil
我们可以检查main
中定义的方法的所有者(发生在Object
):
method(:foo).owner
#=> Object
这意味着您无法区分main
和Object
中定义的方法。
在Ruby 2.2.1上,它成为Object
的公共实例方法:
Object.public_method_defined?(:foo)
#=> true
答案 3 :(得分:0)
最后,他们似乎是相同的,正如安德烈·迪内科的回答所说的那样。但是,我担心的是在main
上定义一个方法应该导致在main
的单例类上定义一个实例方法,这与类Object
不同。例如,如果我在普通对象上定义一个方法,我可以看到它成为其单例类的实例方法:
s = ""
def s.bar; end
s.singleton_class.instance_methods(false) # => [:bar]
然而,对于main
,它是不同的。在main
上定义方法不会导致它成为其单例类的实例方法。返回的列表不包括:foo
:
def foo; end
singleton_class.instance_methods(false)
# => [:inspect, :to_s, :source, :kill, :exit, :conf, :context, :irb_quit, :quit, :irb_print_working_workspace, :irb_cwws, :irb_pwws, :cwws, :pwws, :irb_current_working_binding, :irb_print_working_binding, :irb_cwb, :irb_pwb, :irb_chws, :irb_cws, :chws, :cws, :irb_change_binding, :irb_cb, :cb, :workspaces, :irb_bindings, :bindings, :irb_pushws, :pushws, :irb_push_binding, :irb_pushb, :pushb, :irb_popws, :popws, :irb_pop_binding, :irb_popb, :popb, :jobs, :fg, :help]
所以看起来该方法会跳转main
的单例类,并直接在Object
上定义。因此,他们无法区分。