所以我开始学习ruby,我发现我们可以在方法中使用默认值,这看起来类似于只有实例变量,除了减少代码行之外,这是否有任何重要性或好处?
//这
def order_food(price, size="large", quantity = 8)
if quantity == 1
extra = "salad"
else
extra = "Burgers"
end
puts "#{quantity} #{size} #{extra}, coming right up!"
end
//到此
def order_food(price)
size = "large"
quantity = 8
if quantity == 1
extra = "salad"
else
extra = "Burgers"
end
puts "#{quantity} #{size} #{extra}, coming right up!"
end
答案 0 :(得分:4)
在深思熟虑的同时,我意识到这提供了一个非常大的好处是灵活性和可读性。 例如,我可以传递像
这样的参数order_food(2, "small", 90)
这允许我覆盖默认值,这比在
时更改变量内容更好order_food(9, "extraLarge")
获取我设置的默认数量
答案 1 :(得分:3)
它与实例变量不同。实例变量具有类实例的范围,并使用@
符号声明。
例如:
class MyClass
def initialise
@my_instance_variable = 'hello world'
end
def method_one
puts "I have access to the instance variable and it is #{@my_instance_variable}"
end
end
你所展示的只是方法范围的局部变量声明,但是一个是为你的方法定义一个参数而另一个是没有。
def order_food(price, size="large", quantity = 8)
相当于:
def order_food(price)
size = "large"
quantity = 8
虽然大小和数量都是变量,并且两者都只有order_food
方法的范围,但第一种方法是将它们声明为方法可以接受的参数,因此可以这样调用:
order_food(5, 'small', 2)
而在第二个例子中,这些不能由被叫者设定 - 它们固定在“大”的位置。和8。
没有必要使用默认值声明方法参数,但通过这样做,被调用者不需要提供它们,而是使用默认值。所以对于方法声明:
def order_food(price, size="large", quantity = 8)
您可以拨打以下电话:
order_food price: 10, quantity: 2 #will use default size with value 'large'
order_food price: 5, size: 'small' #will use default quantity of 8
答案 2 :(得分:2)
首先,变量是局部变量而不是实例变量。实例变量属于类的实例,并以@var_name
表示法标注,而局部变量属于范围(非常简单,即do ... end
所包围的任何内容。更详细here并且仅使用变量名称(my_var = "some_value"
)进行标注。
这取决于您使用该方法的内容。如果您希望能够传递参数quantity
和size
,那么您应该使用第一个参数。如果你尝试传递超过1个参数,第二个将给你和ArgumentError
。第一个将设置quantity = 8
和size = "large"
的值,如果它们没有被传递,但如果它们被传递,它将使用传递的值。
如果您希望能够调用方法并将大小和数量设置为参数,如果未传递它们,请使用size = "large"
和quantity = 8
作为默认值,使用第一种方法:
order_food "9.00" #=> "8 large burgers, coming right up!"
order_food "9.00", "small", 1 #=> "1 small salad, coming right up!"
第二种方法不允许您传递其他两个参数中的任何一个,并且它们将始终设置为quantity = 8
和size = "large"
。这有其好处,因为有时您不希望变量可以通过参数进行更改。所以使用第二种方法:
order_food "9.00" #=> "8 large burgers, coming right up!"
order_food "9.00", "small", 1 #=> ArgumentError: wrong number of arguments (given 3, expected 1)
答案 3 :(得分:1)
这是一个重新编写的代码版本,它更像Ruby:
def order_food(price, size: :large, quantity: 1)
extras =
case (quantity)
when 1
"salad"
else
"Burgers"
end
"#{quantity} #{size} #{extra}, coming right up!"
end
puts order_food(2, :small, 8)
在方法中进行显示(puts
)通常会给方法带来太多责任。从构成问题中分离显示问题。也许您想将其写入文件,或将其嵌入HTML中。方法中的puts
限制了您的选择。
如果你想拥有一些本质上有些随意的数量,也可以利用关键字参数。这允许您跳过一个并使用另一个而不需要重新指定默认值的代码。
答案 4 :(得分:0)
实际上有4种将参数传递给函数的常用方法。 你的第一个例子是最常见的例子,但是我害怕你做了一个坏榜样。你的数量总是8,所以if是多余的,也没有使用参数价格所以也是多余的 这与以下
相同 def order_food price
"8 large Burgers, coming right up!"
end
但我认为这不是你的目的。
所以,它会是这样的 第一种方法
def order_food1(size, quantity, price)
extra = quantity == 1 ? :salad : :Burgers
cost = quantity * price
"#{quantity} #{size} #{extra}, coming right up! Thats is #{cost} dollar please"
end
+快(见基准)
+每个人都使用它并在一个glace中理解它
- 您必须知道参数及其定义的顺序,您需要阅读不太常用的API方法
- 您必须提供所有参数
下一步:使用带默认值的可选参数
def order_food2(size = "large", quantity = 1, price = 4)
extra = quantity == 1 ? :salad : :Burgers
cost = quantity * price
"#{quantity} #{size} #{extra}, coming right up! Thats is #{cost} dollar please"
end
+也广泛使用
+如果参数是默认参数,则无需使用参数
- 你仍然需要知道参数的顺序和含义,如果使用了最后一个,你需要它们
下一步:使用哈希作为参数
def order_food3(opts = {})
opts = {size: :large, quantity: 1, price: 4}.merge!(opts)
extra = opts[:quantity] == 1 ? :salad : :Burgers
cost = opts[:quantity] * opts[:price]
"#{opts[:quantity]} #{opts[:size]} #{extra}, coming right up! Thats is #{cost} dollar please"
end
- 少用,你的方法自我有点难以阅读
- 慢点
+无需知道您不需要的参数,也无需知道订单
+使用该方法更具可读性
下一步:上一种方法的简化版
def order_food4(size: :large, quantity: 1, price: 4)
extra = :quantity == 1 ? :salad : :Burgers
cost = quantity * price
"#{quantity} #{size} #{extra}, coming right up! Thats is #{cost} dollar please"
end
- 慢点
+方法本身及其使用更具可读性
哪一个更好?取决于个人品味和情况。 我使用了所有这些,据我所知,设计指南中没有任何内容可以说是其中之一。 在实践中,你甚至可以将其中一些组合起来。 很少更改的参数最好给出默认值,反之亦然。 多次调用的方法(例如递归方法)可以从更快且更少消耗内存的方法1中受益。 在我看来,可读性对于Ruby脚本来说是最重要的,所以如果有很多参数和可行的使用方法3或4。
使用和基准的一些例子..
puts order_food1("large", 3, 4)
puts order_food2("large", 3, 4)
puts order_food3(size: "large", quantity: 3, price: 4)
puts order_food3
puts order_food4(size: "large", quantity: 3, price: 4)
puts order_food4
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 1 large salad, coming right up! Thats is 4 dollar please
# 3 large Burgers, coming right up! Thats is 12 dollar please
# 1 large Burgers, coming right up! Thats is 4 dollar please
require 'benchmark'
Benchmark.bmbm do |x|
x.report("order_food1 ") { 10000.times { order_food1("large", 3, 12) }}
x.report("order_food2 ") { 10000.times { order_food2("large", 3, 12) }} # all parameters given
x.report("order_food2_def") { 10000.times { order_food2 }} # using default parameters
x.report("order_food3 ") { 10000.times { order_food3(size: "large", quantity: 3, price: 12) }} # all parameters given
x.report("order_food3 def") { 10000.times { order_food3 }} # using default parameters
x.report("order_food4 ") { 10000.times { order_food3(size: "large", quantity: 3, price: 12) }} # all parameters given
x.report("order_food4 def") { 10000.times { order_food3 }} # using default parameters
end
# user system total real
# order_food1 0.015000 0.000000 0.015000 ( 0.010420)
# order_food2 0.000000 0.000000 0.000000 ( 0.010675)
# order_food2_def 0.016000 0.000000 0.016000 ( 0.011007)
# order_food3 0.015000 0.000000 0.015000 ( 0.020182)
# order_food3 def 0.016000 0.000000 0.016000 ( 0.016954)
# order_food4 0.015000 0.000000 0.015000 ( 0.020256)
# order_food4 def 0.000000 0.000000 0.000000 ( 0.016968)