请问我"为什么要这样做?"我只是在探索Ruby的角落和缝隙,没有具体的目标.

有些Ruby类可以用括号实例化,而不是显式调用#new方法. 例如,

irb> require 'pathname'
irb> p=Pathname('/etc/xdg/autostart')
  => #<Pathname:/etc/xdg/autostart>
irb> n=Pathname.new('/etc/xdg/autostart')
  => #<Pathname:/etc/xdg/autostart>
irb> p==n
  => true

有些人用这个来做施法/胁迫,比如Integer(4.5). 可能还有其他的用途我还没有遇到,或者记不清了.

然而,我还没有找到一种方法来实现自定义类:

irb> class Foo ; def initialize(*args) ; @args=args ; end ; end
  => :initialize
irb> f1=Foo.new(1,2,3)
  => #<Foo:0x00007f330a29f4e8 @args=[1, 2, 3]>
irb> fp=Foo(1,2,3)
(irb):7:in `<main>': undefined method `Foo' for main:Object (NoMethodError)
Did you mean?  for

我唯一能弄清楚的是,PathnameInteger(例如)都使用C代码,并且不知何故是内核方法:

irb> Object.method(:Pathname)
  => #<Method: #<Class:Object>(Kernel)#Pathname(_)>
irb> Object.method(:Integer)
  => #<Method: #<Class:Object>(Kernel)#Integer(*)>
irb> Object.method(:Foo)
(irb):10:in `method': undefined method `Foo' for class `#<Class:Object>' (NameError)
Did you mean?  for

所以这似乎是C/.so扩展代码提供的.

然而,是否可以简单地使用原生Ruby代码而不诉诸于类似以下的笨拙?

irb> Object.define_method(:Foo) { |*args| Foo.new(*args) }
  => :Foo
irb> Foo(1,2,3)
  => #<Foo:0x00007f330a3b9018 @args=[1, 2, 3]>

推荐答案

这些全局方法被称为module functions,定义在Kernel中.你可以这样定义你自己的全局函数:(使用Ruby 3的简写语法来定义methods)

module Kernel
  def Foo(...) = Foo.new(...)
  module_function :Foo
end

以上定义了方法Kernel#Foo,其forwards all argumentsFoo.new.由于Object包括Kernel,这允许通过以下方式从对象内创建Foo个实例:

Foo(1, 2, 3) #=> #<Foo:0x000000010633e120 @args=[1, 2, 3]>

另外,module_function使方法作为类方法可用:

Kernel.Foo(1, 2, 3) #=> #<Foo:0x0000000108b00398 @args=[1, 2, 3]>

它还将实例方法标记为private,所以你不能用任何其他显式接收器调用它:

:hello.Foo(1, 2, 3)
# NoMethodError: private method `Foo' called for an instance of Symbol

这也是IntegerPathname等的整合方式.

注意,对应于一个类的内置全局方法主要用于该类的converting个值,例如Integer("123") #=> 123.他们不只是传递论点.(Integer不回应new)

Ruby相关问答推荐

Ruby迭代器与函数.返回函数的第一个值,而不交互整个列表

如何查询哪些RuboCop规则适用于文件?

在 Ruby 中,如何从派生类中重写同一方法的不同方法调用基类方法?

为什么我的二维 Ruby 数组的多个值会发生变化,尽管只更改了其中一个?

Ruby注入daisy链?

.nil?、.blank? 之间的区别?和.empty?

有人可以解释 Ruby 在块中使用管道字符吗?

Simple_form:删除带有标签的内联复选框的外部标签

Ruby:通过正则表达式过滤数组?

Ruby 中的 STDIN 和 $stdin 有什么区别?

Ruby 中的字符串是可变的吗?

无法从同一网络上的另一台计算机访问本地 Sinatra 服务器

Rails 在最后一个之前加入逗号和and的字符串列表

如何在 Ruby 中使用 (n) 诅咒?

文字数字中的下划线是什么意思?

在 ruby​​ 的超类中调用另一个方法

Ruby 中的超级关键字

未加载库:/opt/local/lib/libssl.1.0.0.dylib (LoadError)

如何使用 Ruby-Rails 删除文件夹的所有内容?

什么是 Ruby 1.9 标准 CSV 库?