通过点调用的 Ruby 函数

del*_*pha 2 ruby

我想调用一个名为my_format_number如下的函数:

num = 5.5
formated_num = num.my_format_number
Run Code Online (Sandbox Code Playgroud)

我怎样才能在 Ruby 中做到这一点?这些类型的函数的名称是什么?

das*_*s-g 6

这些类型的函数的名称是什么?

在面向对象编程(独立于编程语言)中,绑定到对象(通常通过对象的类)的函数称为“方法”。不过,一些 Ruby 文档将所有函数都称为“方法”。为区分起见,我将使用“方法”仅表示绑定函数,并继续将一般的函数称为“函数”。

未绑定到对象的函数通常称为“自由函数”。

方法绑定到的对象称为方法的“接收者”。

我怎样才能在 Ruby 中做到这一点?

在 Ruby 中,方法总是实例方法:它们在类上定义,但作用于类的实例。(即,接收者必须是一个实例。)除了在 C/C++ 或 Java 中,Ruby 中的所有值都是对象(类的实例),因此每个值都有一个类。

班级?什么级别?

类是值/对象/实例的类型。它确定(在某种程度上)值的语义,以及对该值可用的方法。

什么是班级5.5?让我们来了解一下:

(5.5).class()
# => Float
Run Code Online (Sandbox Code Playgroud)

(较短的5.5.class也可以,但有点难以理解。)

Float 是 Ruby 的内置浮点数类。

修改Float

Ruby 中的类定义可以拆分和分发。每个块在解释后都会生效,除了已经生效的块之外,这意味着您可以在运行时修改类。这被称为“猴子修补”或“重新开设课程”。

让我们重新打开Float类并添加my_format_number方法。我决定它应该返回一个字符串:

class Float
  def my_format_number
    return "The number is #{self} and #{self} is the number."
  end
end
Run Code Online (Sandbox Code Playgroud)

return字符串前面的可以被跳过,因为 Ruby 函数隐式返回它们计算的最后一个表达式。)

现在您可以对所有Float值调用新方法:

num = 5.5
formatted_num = num.my_format_number()
puts(formatted_num)
# The number is 5.5 and 5.5 is the number.
Run Code Online (Sandbox Code Playgroud)

我们甚至不需要变量,可以直接在值文字上调用该方法:

puts 7.8.my_format_number
# The number is 7.8 and 7.8 is the number.
Run Code Online (Sandbox Code Playgroud)

但是,它不适用于所有数字:

100.my_format_number
# NoMethodError: undefined method `my_format_number' for 100:Fixnum
#   from (irb):15
#   from :0
Run Code Online (Sandbox Code Playgroud)

那是因为我们定义了Floatand的数量100(正如错误消息告诉我们的那样)不是 aFloat而是 a Fixnum(一种特殊的Integer)。

一次修改几个相关的类

您现在当然也可以定义Fixnum. 但是有些数字既不是Fixnums 也不Float是 s。因此,在某个中心位置拥有该功能是有意义的。

我们可以修补 Ruby 的大师班,Object. 但这将允许

"foobar".my_format_number
Run Code Online (Sandbox Code Playgroud)

return "The number is foobar and foobar is the number.",这是没有意义的,因为foobar它不是数字。我只想要我们的方法来格式化数字。

让我们看看类的Fixnum结构:

Fixnum.superclass()
# => Integer
Fixnum.superclass().superclass() # equivalent to `Integer.superclass`
# => Numeric
Fixnum.superclass().superclass().superclass() # equivalent to `Numeric.superclass`
# => Object
Run Code Online (Sandbox Code Playgroud)

superclass方法只为我们提供了一个直接祖先。使用 Ruby 模块,多重继承是可能的,因此我们可以得到更多这样的结果:

Fixnum.ancestors
# => [Fixnum, Integer, Precision, Numeric, Comparable, Object, Kernel]
Run Code Online (Sandbox Code Playgroud)

让我们看看重叠是什么

Float.ancestors()
# => [Float, Precision, Numeric, Comparable, Object, Kernel]
Run Code Online (Sandbox Code Playgroud)

Comparable可能比数字更笼统,而Precision可能过于具体甚至有些不相关。(它可能是一个模块。)让我们Numeric这样修改,这(从它的名字猜测)听起来像是正确的抽象级别。事实上,文档称它为

顶级数字类。

因此,与之前非常相似,

class Numeric
  def my_format_number
    return "The number is #{self} and #{self} is the number."
  end
end
Run Code Online (Sandbox Code Playgroud)

现在

100.my_format_number
# => "The number is 100 and 100 is the number."
Run Code Online (Sandbox Code Playgroud)

如果您想知道我们在第二次猴子补丁中添加了该方法的所有类,请查看在 Ruby查找类的所有后代