2

Rubyで出力引数を持つメソッドを作ろうとしています。

ルビーがその引数を値渡しにするか参照渡しにするかについての議論について、ここここでさまざまな投稿を読みました。

厳密に言えば、Ruby は常に値渡しですが、渡される値は実際には参照です。これについて多くの議論がある理由。

参照された変数の値を変更するには、いくつかの方法があることがわかりました。たとえば、配列、ハッシュ、文字列、またはマージの場合は、 replaceメソッドを使用します。ハッシュの場合。

integerを使用すると、特別なメソッドを使用しなくても、メソッドの外部で値を変更して渡すことができることがわかりました。

私の質問は他のオブジェクトについてです。たとえば、オブジェクトの「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 は nil のままです)

4

4 に答える 4

3

ほとんどの場合、outパラメーターは、複数値の戻り値がない言語の回避策です。Rubyでは、関数のすべての出力値を含む配列を返すだけです。または、可変値をオブジェクトのインスタンス変数にし、関数をそのオブジェクトのメソッドにします。

于 2013-02-20T03:06:07.120 に答える
3

Python や Java と同じように、Ruby には値渡ししかありません。また、Python や Java と同様に、オブジェクトは直接値ではなく、参照を通じて操作されます。

ローカル変数への割り当ては、呼び出し元のスコープにはまったく影響しません。また、情報を返す以外に呼び出し元スコープと情報を「共有」するには、渡された参照が指すオブジェクトを「変更」するメソッドを使用する必要があります (そのようなメソッドが存在する場合、つまり、オブジェクトが変更可能な場合)。 . ただし、これは、必要な新しいオブジェクトへの参照を与えるのではなく、同じオブジェクトを変更するだけです。

値を返したくない場合は、変更可能なコンテナー (1 つの要素の配列など) を渡して、呼び出された関数が変更してそこに何でも入れて、呼び出し元のスコープで表示できるようにすることができます。

別のオプションは、関数にブロックを持たせることです。関数はブロックに の新しい値をpizza与え、ブロック (呼び出し元によって与えられる) はそれをどうするかを決めることができます。呼び出し元は、ピザを独自のスコープに設定するだけのブロックを渡すことができます。

于 2013-02-19T22:08:49.630 に答える
0

両方の答えをありがとう。

私はついに同等の解決策を思いついたようです:可変コンテナ

メソッドから出力したいパラメーターを( attr_accessorsOutputParameterとして)含む新しいクラス''を作成しました。次に、このクラスのインスタンスをメソッドに渡しました。

  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
于 2013-02-21T14:08:16.867 に答える
0

次のように複数の戻り値を使用できます。

def maybe_get_something
  ...
  return nil, "sorry" if bad_condition
  ...
  something, nil
end

...
something, err = maybe_get_something
if !err.nil?
  handle(err)
  return
end
do_something_with(something)

Goを使用するときに人々が行うことと非常によく似ています。

f, err := os.Open("filename.ext")
if err != nil {
    log.Fatal(err)
}
// do something with the open *File f
于 2018-03-25T07:06:59.613 に答える