我有两个类的以下代码
class DeliveryService
attr_reader :cities
def initialize *cities
@cities = cities
end
end
class Product
attr_accessor :name
def initialize name
@name = name
end
def deliver_to delivery_service, city
if delivery_service.cities.include?(city)
puts "Product has been delivered"
else
puts "Сontact another delivery service"
end
end
end
我想deliver_to
方法抛出类似"选择有效的送货服务"提供无效delivery_service
时(不存在),但我得到NameError
我试着将它放在我的代码中的不同位置
rescue NameError
puts "Choose valid delivery service"
但它不起作用
irb(main):001:0> require './DeliveryService.rb'
=> true
irb(main):002:0> fedex = DeliveryService.new "Moscow", "Saint-Petersburg"
=> #<DeliveryService:0x007f66ded31520 @cities=["Moscow", "Saint-Petersburg"]>
irb(main):003:0> product = Product.new "mug"
=> #<Product:0x007f66ded1e498 @name="mug">
irb(main):004:0> product.deliver_to fedex, "Moscow"
Product has been delivered
=> nil
irb(main):005:0> product.deliver_to dhl, "Moscow"
NameError: undefined local variable or method `dhl' for main:Object
from (irb):6
from /home/budkin/.rbenv/versions/2.1.2/bin/irb:11:in `<main>'
irb(main):006:0>
答案 0 :(得分:1)
这是一个设计问题,因为您没有从类中获取NameError;当你从班级外面打电话给product.deliver_to dhl, "Moscow"
时,它就会被提升。即使你有一个救援子句作为你的类定义的一部分,也会由调用者引发。
解决此问题的正确方法是将有效的Product对象传递给有效的DeliveryService对象。产品不应该对交货情况有任何了解;这违反了单一责任原则。所以:
class DeliveryService
def deliver product
end
end
这将为您提供一个实例方法,该方法接收产品,并通过当前的传递服务提供。例如:
product = Product.new :widget
dhl = DeliveryService.new 'Moscow'
dhl.deliver product
即使您执行此反转,如果您传递无效对象也会遇到问题,所以不要这样做。 :)
答案 1 :(得分:0)
dh1
不存在,因此您需要包含尝试取消引用dh1
的部分代码。
begin
product.deliver_to dhl, "Moscow"
rescue NameError => e
puts e.message
end
虽然这是一个非常混乱的方法。更好的方法是创建包含所有公司的array
或set
,然后检查公司是否已在set
/ array
中定义。