11

作为 Ruby 的新手,我很难向自己解释Ruby 中方法定义的行为。

该示例如下所示...

class Foo
  def do_something(action)
    action.inspect
  end
  def do_something_else=action 
    action.inspect
  end
end

?> f.do_something("drive")
=> "\"drive\""

?> f.do_something_else=("drive")
=> "drive"

第一个例子是不言自明的。我试图理解的是第二个例子的行为。除了看起来是一个产生字符串文字而另一个不是,实际发生了什么?为什么我要使用其中一个?

4

4 回答 4

14

一般来说,do_something是一个getter,并且do_something=是一个setter。

class Foo
  attr_accessor :bar
end

相当于

class Foo
  def bar
    @bar
  end

  def bar=(value)
    @bar = value
  end
end

为了回答您关于行为差异的问题,以结尾的方法=始终返回表达式的右侧。在这种情况下返回action,不是action.inspect

class Foo
  def do_something=(action)
    "stop"
  end
end

?> f = Foo.new
?> f.do_something=("drive")
=> "drive"
于 2012-10-10T04:31:04.147 回答
10

您的两个方法实际上都被定义并称为方法。Ruby 中的很多东西都可以定义为方法,甚至包括、+和等运算符。Ruby 允许方法具有三个特殊的符号后缀。这句话是我自己编出来的。我所说的符号后缀的意思是方法末尾的东西将指示该方法应该如何工作。-*/

砰!

第一个符号后缀!. 这表明该方法应该是破坏性的,这意味着它修改了调用它的对象。比较这两个脚本的输出:

a = [1, 2, 3]
a.map { |x| x * x }
a

和:

a = [1, 2, 3]
a.map! { |x| x * x }
a

两个脚本之间有一个字符差异,但它们的操作方式不同!第一个仍将遍历数组中的每个元素并在块内执行操作,但其中的对象a仍将与[1,2,3]您开始时相同。

然而,在第二个示例中,a最后的 将改为[1, 4, 9]因为map!修改了对象!

询问

第二个符号后缀?, 表示方法用于查询对象的某事,并表示该方法应该返回truefalse或者在某些极端情况下nil

现在,请注意该方法不必返回truefalse......只是如果它这样做会非常好!

证明:

def a?
  true
end

def b?
  "moo"
end

调用a?会返回true,调用b?会返回“moo”。这就是查询方法。应该返回true或但有时可以返回其他东西的方法,false因为一些开发人员不喜欢其他开发人员。

二传手!

现在我们进入您(转述)问题的核心:方法结束是什么=意思?

这通常表明一个方法将设置一个特定的值,正如Erik在我写完这篇答案之前已经概述的那样。

但是,它可能不会设置一个,就像查询方法可能不会返回trueor一样false。这只是惯例。

您也可以像这样调用该 setter 方法:

foo.something_else="value"

或者(我最喜欢的):

foo.something_else = "value"

理论上,您实际上可以忽略传入的值,就像您可以完全忽略传递给任何方法的任何参数一样:

def foo?(*args)
  "moo"
end

>> foo?(:please, :oh, :please, :why, :"won't", :you, :use, :these, :arguments, :i, :got, :just, :for, :you, :question_mark?)
=> "moo"

Ruby 支持 setter 方法的所有三种语法,尽管很少见到您使用的那种!

好吧,我希望这个答案大致具有教育意义,并且您现在了解更多关于 Ruby 的知识。享受!

于 2012-10-10T04:41:46.443 回答
3

您不能为赋值方法定义返回值。返回值始终与传入的值相同,因此分配链 ( x = y = z = 3) 将始终有效。

通常,您在调用该方法时会省略括号,以便它的行为类似于属性:

my_value = f.do_something= "drive"
于 2012-10-10T04:32:14.320 回答
0
def do_something_else=action 
  action.inspect
end

这定义了一个 setter 方法,所以 do_something_else 看起来好像我们正在初始化一个属性。所以直接传入初始化的值,

于 2012-10-10T04:34:54.697 回答