如何使用实例变量完成相同的任务?

时间:2014-01-27 08:09:24

标签: ruby hash

这里我使用全局变量来存储列表,因为我无法弄清楚如何保持列表的长度足以检查其重复值。

$list = []
def hand_out_gift(name)
  if $list.include?name 
    puts "No present for you"
  else 
    $list.push(name)
  end
end

hand_out_gift("Peter")
hand_out_gift("Alison")
hand_out_gift("John")
hand_out_gift("Maria")
hand_out_gift("Peter")

如何使用实例变量完成相同的检查?

2 个答案:

答案 0 :(得分:0)

global variableinstance variable之间的差异global variables$开头,instance variables@和{{1}开头全局可访问,而实例变量只能由对象的实例访问

global variables

答案 1 :(得分:0)

当您使用面向对象的代码处理问题时,Ruby效果最佳。

通常情况下,您需要将数据视为具有自己属性和方法的对象,而不是将数据结构视为您正在处理的范围的结果(在您的示例中为全局数据,或者本地如果您根据其他答案编辑它。)

这是一个令人费解的例子来说明:

class Party
  def initialize(members = nil)
    @members = {}
    invite(*members) if members
  end

  def members
    @members.values
  end

  def invite(*members)
    members = Hash[members.map { |member|
      if member.is_a?(Member)
        [member.name.downcase, member]
      else
        [member.downcase, Member.new(member)]
      end
    }]
    @members = members.merge(@members)
  end

  def find(member)
    if member.is_a?(Member)
      key = member.name
    else
      key = member
    end
    @members[key.downcase]
  end
end

我们可以在旁边定义一个成员对象。

class Member
  attr_reader :name, :gift

  def initialize(name)
    @name = name
  end

  def has_gift?
    !!@gift
  end

  def gift=(gift)
    raise if has_gift?
    @gift = gift
  end
end

我们可以使用:

来调用它
members = ["Peter", "Alison", "John", "Maria"]
party = Party.new(members)
party.members.each { |m| m.gift = true }
party.find("Peter").gift = :foo

(完全未经测试的代码,因此您希望原谅潜在的语法错误。)

在上文中,Party负责管理(和索引)成员列表。会员最终负责检查该会员是否收到礼物。每个他自己的属性和各种方法。

我可以(实际上应该)在该Party对象中使用了Set对象而不是Hash。请注意如何封装此内部表示并从不暴露它意味着您可以稍后将其更改为Set,而不会对其余代码产生任何有害影响。其他地方唯一的变化是需要定义如何散列成员。