1

我想在ruby中輸出參數。如何使Ruby方法傳遞輸出參數(更改引用參數的值)?

我看了型動物的帖子herehere約羯羊紅寶石的討論,通過它的參數的值或引用和

我undersand上嚴格的桑斯,紅寶石總是傳遞按值,但傳遞的價值實際上是一種參考。爲什麼有這麼多的辯論的原因。

我發現有幾種方法可以改變被引用變量的值。 例如用替換的方法,當它的一個Array,一個Hash或一個String或合併時!當它是一個散列。

我發現與整數,我可以改變和傳遞值以外的方法沒有任何特殊的方法使用。

我的問題是關於其他物體。 比如我要檢索對象的「id」屬性,和對象引用本身:

class RestaurantController < ApplicationController 
    def pizza_to_deliver(pizza_name, id_of_the_order, pizza) 

     # pizza to eat 
     pizza = Pizza.where(:name => pizza_name).first 

     # unknown pizza 
     return false if pizza.nil? 

     # first customer order about this pizza 
     id_of_the_order = Orders.where(:pizza_id => pizza.id).first 

     true 
    end 
    end 

my_pizza_name = 'margerita' 
My_order_id = nil 
my_pizza = nil 

my_restaurant = RestaurantController.new 

if my_restauant.pizza_to_deliver(my_pizza_name, My_order_id, my_pizza) then 
    puts "Pizza to deliver : #{my_order_id}" 
    rex_dog.eat(my_pizza) 
end 

如何使這個工作? (order_id和my_pizza仍然爲零)

回答

2

Ruby只是像Python和Java那樣通過值傳遞。與Python和Java一樣,對象也不是直接值,而是通過引用進行操作。

看來你已經明白它是如何工作的 - 分配給本地變量從不會對調用者範圍產生任何影響。除了返回之外,要與調用者作用域「共享」信息,您必須在對象上使用某種方法來「mutate」對象(如果這種方法存在;即,如果對象是可變的),這是由傳入的引用指向的。但是,這只是簡單地修改同一個對象,而不是提供一個你想要的新對象的引用。

如果你不願意返回值,你可以傳遞一個可變容器(就像一個元素的數組),然後被調用的函數可以進行變異,然後放入任何內容並在調用者範圍內看到它。

另一個選擇是讓函數佔用一個塊。該函數將爲該塊賦予pizza的新值,然後該塊(由調用者給出)可以決定如何處理它。調用者可以傳遞一個塊,它可以將比薩餅設置在自己的範圍內。

2

大多數情況下,out參數是沒有多值返回的語言的解決方法。在Ruby中,我只是返回一個包含該函數所有輸出值的數組。或者在對象中創建可變值實例變量,並在該對象上創建一個方法。

0

謝謝你的答案。

看來我終於拿出了等價的解決方案:可變容器

我創建了一個新類「OutputParameter」,其中包含(我想要從我的方法輸出的參數(如attr_accessors)。然後,我將這個類的一個實例傳遞給了我的方法。

class OutputParameters 
    attr_accessor :order_id, pizza 
    end 

    class RestaurantController < ApplicationController 
    def pizza_to_deliver(pizza_name, output_parameters) 

     # pizza to eat 
     pizza = Pizza.where(:name => pizza_name).first 

     # unknown pizza 
     return false if pizza.nil? 

     # first customer order about this pizza 
     id_of_the_order = Orders.where(:pizza_id => pizza.id).first 

     # Output values returned 
     output_parameters.pizza = pizza 
     output_parameters.order_id = id_of_the_order 
     true 
    end 
    end 

my_pizza_name = 'margerita' 
my_output = OutputParameters.new 
my_restaurant = RestaurantController.new 

if my_restaurant.pizza_to_deliver(my_pizza_name, my_output) then 
    puts "Pizza to deliver : #{my_output.order_id}" 
    rex_dog.eat(my_output.pizza) 
end 

你建議的散列或數組似乎連一個好主意,因爲它是更適應性:我不會要聲明一個類。

我只是使用合併!方法

class RestaurantController < ApplicationController 
    def pizza_to_deliver(pizza_name, output_hash) 

     # pizza to eat 
     pizza = Pizza.where(:name => pizza_name).first 

     # unknown pizza 
     return false if pizza.nil? 

     # first customer order about this pizza 
     id_of_the_order = Orders.where(:pizza_id => pizza.id).first 

     # Output values returned 
     output_hash.merge!({:pizza => pizza}) 
     output_hash.merge!({:id_of_the_order => id_of_the_order}) 
     true 
    end 
    end 

my_pizza_name = 'margerita' 
my_output_hash = {} 
my_restaurant = RestaurantController.new 

if my_restaurant.pizza_to_deliver(my_pizza_name, my_output_hash) then 
    puts "Pizza to deliver : #{my_output_hash[:id_of_the_order]}" 
    rex_dog.eat(my_output_hash[:pizza]) 
end