从数组中的对象中删除实例变量

时间:2011-08-24 14:47:47

标签: ruby

我是Ruby的新手,我只是在玩想法,我想要做的是从我创建的country_array中删除@continent数据。完成了大量的搜索,可以找到有关完整删除元素的相关信息,但无法找到如何专门删除@continent数据。请保持任何答案相当简单,因为我是新手,但任何帮助都非常感激。

class World
  include Enumerable
  include Comparable

  attr_accessor :continent
  def <=> (sorted)
    @length = other.continent
  end

  def initialize(country, continent)
    @country = country
    @continent = continent
  end 
end

a = World.new("Spain", "Europe")
b = World.new("India", "Asia")
c = World.new("Argentina", "South America")
d = World.new("Japan", "Asia")

country_array = [a, b, c, d]

puts country_array.inspect

[#<World:0x100169148 @continent="Europe", @country="Spain">, 
#<World:0x1001690d0 @continent="Asia", @country="India">, 
#<World:0x100169058 @continent="South America", @country="Argentina">, 
#<World:0x100168fe0 @continent="Asia", @country="Japan">]

3 个答案:

答案 0 :(得分:15)

您可以使用remove_instance_variable。但是,由于它是一个私有方法,您需要重新打开您的类并添加一个新方法来执行此操作:

class World
  def remove_country
    remove_instance_variable(:@country)
  end
end

然后你可以这样做:

country_array.each { |item| item.remove_country }
# => [#<World:0x7f5e41e07d00 @country="Spain">, 
      #<World:0x7f5e41e01450 @country="India">, 
      #<World:0x7f5e41df5100 @country="Argentina">, 
      #<World:0x7f5e41dedd10 @country="Japan">] 

答案 1 :(得分:3)

以下示例将为您的数组中的第一个@continent对象设置nilWorld

country_array[0].continent = nil

irb(main):035:0> country_array[0]
=> #<World:0xb7dd5e84 @continent=nil, @country="Spain">

但它并不真正删除大陆变量,因为它是World对象的一部分。

您是否在面向对象编程方面做了多少工作?您的书籍或教程中的World示例是某处吗?我建议对World的结构进行一些更改。 World可以包含Continent个数组,每个Continent可以包含Country个数组。

名称具有意义,变量名称应反映其真实含义。 country_array变量可以重命名为world_array,因为它是World个对象的数组。

答案 2 :(得分:0)

99%的时间我建议不要删除实例变量,因为它是额外的代码,没有额外的好处。

当你编写代码时,通常你会尝试解决现实问题。使用实例变量,要问的一些问题是:

  • 我尝试使用变量可以处于的各种状态来建模真实世界的概念吗?
  • 我将如何处理存储在变量中的值?

如果您只是试图清空存储在World对象中的大陆值,则可以将@continent设置为nil,因为粉尘机会说。这对于99%的案例都适用。 (无论如何,访问已删除的实例变量只会返回nil。)

在删除实例变量时,唯一可能的情况(我能想到)可能是有用的是当您缓存可能为nil的值时。例如:

class Player
  def score(force_reload = false)
    if force_reload
      # purge cached value
      remove_instance_variable(:@score)
    end

    # Calling 'defined?' on an instance variable will return false if the variable
    # has never been set, or has been removed via force_reload.
    if not defined? @score
      # Set cached value.
      # Next time around, we'll just return the @score without recalculating.
      @score = get_score_via_expensive_calculation()
    end

    return @score
  end

  private
  def get_score_via_expensive_calculation
    if play_count.zero?
      return nil
    else
      # expensive calculation here
      return result
    end
  end
end

由于nil@score的有意义值,我们无法使用nil来表示该值尚未缓存。因此,我们使用未定义状态告诉我们是否需要重新计算缓存值。因此@score有3种状态:

  1. nil(表示用户未玩过任何游戏)
  2. 号码(表示用户至少玩过一次,但未累积任何积分)
  3. undefined(表示我们尚未获取Player对象的计算得分)。
  4. 现在你可以使用另一个不是数字的值而不是未定义的状态(例如像:unset这样的符号),但这只是一个人为的例子来证明这个想法。有些情况下,您的变量可能包含未知类型的对象。