I'm new to Ruby and I'm just having a play around with ideas and what I would like to do is remove the @continent data from the country_array I have created. Done a good number of searches and can find quite a bit of info on removing elements in their entirety but can't find how to specifically remove @continent data. Please keep any answers fairly simple as I'm new, however any help much appreciated.
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开发者_StackOverflow
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">]
You can use remove_instance_variable
. However, since it's a private method, you'll need to reopen your class and add a new method to do this:
class World
def remove_country
remove_instance_variable(:@country)
end
end
Then you can do this:
country_array.each { |item| item.remove_country }
# => [#<World:0x7f5e41e07d00 @country="Spain">,
#<World:0x7f5e41e01450 @country="India">,
#<World:0x7f5e41df5100 @country="Argentina">,
#<World:0x7f5e41dedd10 @country="Japan">]
The following example will set the @continent
to nil
for the first World
object in your array:
country_array[0].continent = nil
irb(main):035:0> country_array[0]
=> #<World:0xb7dd5e84 @continent=nil, @country="Spain">
But it doesn't really remove the continent variable since it's part of your World
object.
Have you worked much with object-oriented programming? Is your World
example from a book or tutorial somewhere? I would suggest some changes to how your World
is structured. A World
could have an array of Continent
's, and each Continent
could have an array of Country
's.
Names have meaning and variable names should reflect what they truly are. The country_array
variable could be renamed to world_array
since it is an array of World
objects.
99% of the time I would recommend against removing an instance variable, because it's extra code for no extra benefit.
When you're writing code, generally you're trying to solve a real-world problem. With the instance variable, some questions to ask are:
- What real world concept am I trying to model with the various states the variable can be in?
- What am I going to do with the values stored in the variable?
If you're just trying to blank out the continent value stored in a World
object, you can set @continent
to nil
as dustmachine says. This will work fine for the 99% of the cases. (Accessing a removed instance variable will just return nil
anyway.)
The only possible case (I can think of) when removing the instance variable could be useful is when you're caching a value that may be nil
. For example:
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
Since nil
is a meaningful value for @score
, we can't use nil
to indicate that the value hasn't been cached yet. So we use the undefined state to tell us whether we need to recalculate the cached value. So there are 3 states for @score
:
nil
(means user has not played any games)- number (means user played at least once but did not accrue any points)
- undefined (means we haven't fetched the calculated score for the Player object yet).
Now it's true that you could use another value that's not a number instead of the undefined state (a symbol like :unset
for example), but this is just a contrived example to demonstrate the idea. There are cases when your variable may hold an object of unknown type.
精彩评论