簡體   English   中英

Ruby修改參數值

[英]Ruby Modify Argument Value

我現在正在Ruby中練習小寫,並嘗試根據傳遞給相同方法的另一個參數來修改參數的值。 但是,它根本不起作用。

例如:

  class Duck

  attr_reader :foo, :bar

  def initialize
    @foo = false
    @bar = false
  end

  def duck_foo
    ducktype(@foo, @bar)
  end

  def duck_bar
    ducktype(@bar, @foo)
  end

  def ducktype(duck1, duck2)
    p duck1 #=> false
    p duck2 #=> false
    puts "foo: #{foo} bar: #{bar}" #=> "foo: false bar: false"
    duck1 = true if duck2 == false #<= For #duck_foo: I want to make @foo = true if @bar == false. But it only changes duck1 to true. / For #duck_bar: I want to make @bar = true.
    p duck1 #=> true
    p duck2 #=> false
    puts "foo: #{foo} bar: #{bar}" #=> "foo: false bar: false" => @foo is still false. I want it true!
  end

end

duck = Duck.new
duck.duck_foo
duck.duck_bar

我希望看到#duck_foo的輸出是@foo變為true。 但是,它僅將duck1更改為true,而@foo仍為false。

我該如何運作?

本質上,我正在嘗試:

 def duck_foo
    p foo
    p bar
    puts "foo: #{foo} bar: #{bar}"
    @foo = true if @bar == false #=> change @foo to true.
    p foo
    p bar
    puts "foo: #{foo} bar: #{bar}"
  end

  def duck_bar
    p foo
    p bar
    puts "foo: #{foo} bar: #{bar}"
    @bar = true if @foo == false #=> change @bar to true.
    p foo
    p bar
    puts "foo: #{foo} bar: #{bar}"
  end

成:

  def duck_foo
    ducktype(@foo, @bar)
  end

  def duck_bar
    ducktype(@bar, @foo)
  end

  def ducktype(duck1, duck2)
    #whatever code necessary to preserve the original methods' behavior.
  end

因此,代碼更干凈,更易於維護。

希望這是有道理的。 感謝大家!

這里的問題是,您試圖通過分配給局部變量引用來修改實例變量所持有的值。 抱歉,但這在ruby中不起作用-分配給局部變量只會使局部變量指向新對象,而不會影響第一個對象。

但是,您可以做一個很小的修改就可以相當簡單地完成所需的工作(盡管您想使用attr_accessor而不是attr_reader來避開難看的eval塊):

class Duck

  attr_accessor :foo, :bar

  def initialize
    @foo = false
    @bar = false
  end

  def duck_foo
    ducktype(:foo, :bar)
  end

  def duck_bar
    ducktype(:bar, :foo)
  end

  def ducktype(duck1, duck2)
    p send(duck1) #=> false
    p send(duck2) #=> false
    puts "foo: #{foo} bar: #{bar}" #=> "foo: false bar: false"
    send(:"#{duck1}=", true) if send(duck2) == false 
    p send(duck1) #=> true
    p send(duck2) #=> false
    puts "foo: #{foo} bar: #{bar}" #=> "foo: true bar: false"
  end
end

在此實現中,我們沒有傳遞實例變量(傳遞給局部變量時會丟失上下文),而是將我們的意圖作為符號“消息”傳遞。 然后,我們可以根據需要使用這些符號與我們的對象進行交互。

一種方法是檢查object_id

  def ducktype(duck1, duck2)
    puts "foo: #{foo} bar: #{bar}" #=> "foo: false bar: false"
    if duck1.object_id == @foo.object_id
        @foo = true if !duck2
    elsif duck1.object_id == @bar.object_id
        @bar = true if !duck2
    end
    puts "foo: #{foo} bar: #{bar}" #=> "foo: true bar: false"
  end

由於您要傳遞布爾值,因此您無法像在使用Strings一樣使用函數str.replace('true')在函數內更改其值。


什么時候需要檢查object_id

如果@foo@bar是字符串而不是布爾值,則可以執行以下操作:

  def ducktype(duck1, duck2)
    puts "foo: #{foo} bar: #{bar}" #=> "foo: false bar: false"
    duck1.replace('true') if duck2 == 'false'
    puts "foo: #{foo} bar: #{bar}" #=> "foo: true bar: false"
  end

不管其類型為何, duck1 = true都不起作用是因為已為其分配了新實例。 即:

duck1 = true # => true
duck1.object_id # => 2
duck1 = false # => false
duck1.object_id # => 0  <-- id changes
duck1 = 'true' # => "true"
duck1.object_id # => 6563940
duck1.replace('false') # => "false"
duck1.object_id # => 6563940 <-- id stays the same

因此,如果數據類型不具有可以更改其自身值的成員函數,則似乎必須像上面那樣通過檢查object_id來完成此任務。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM