Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.ruby > #4006 > unrolled thread
| Started by | Stefan Salewski <mail@ssalewski.de> |
|---|---|
| First post | 2011-05-05 14:06 -0500 |
| Last post | 2011-05-07 19:51 -0500 |
| Articles | 8 — 5 participants |
Back to article view | Back to comp.lang.ruby
Cross access between instance variables Stefan Salewski <mail@ssalewski.de> - 2011-05-05 14:06 -0500
Re: Cross access between instance variables Josh Cheek <josh.cheek@gmail.com> - 2011-05-05 14:47 -0500
Re: Cross access between instance variables Johannes Held <johannes.held@informatik.uni-erlangen.de> - 2011-05-06 10:23 +0200
Re: Cross access between instance variables Stefan Salewski <mail@ssalewski.de> - 2011-05-07 16:27 -0500
Re: Cross access between instance variables Hassan Schroeder <hassan.schroeder@gmail.com> - 2011-05-07 18:27 -0500
Re: Cross access between instance variables John Feminella <johnf@bitsbuilder.com> - 2011-05-07 18:36 -0500
Re: Cross access between instance variables Hassan Schroeder <hassan.schroeder@gmail.com> - 2011-05-07 19:31 -0500
Re: Cross access between instance variables John Feminella <johnf@bitsbuilder.com> - 2011-05-07 19:51 -0500
| From | Stefan Salewski <mail@ssalewski.de> |
|---|---|
| Date | 2011-05-05 14:06 -0500 |
| Subject | Cross access between instance variables |
| Message-ID | <1304622204.2610.22.camel@AMD64X2.fritz.box> |
I am working on a larger Ruby program, where instance variables of one
class need access to content of another class -- I wonder how I should
solve this problem best.
Assume we have multiple fish tanks, each with multiple fishes. The
fishes should tell us if they like the temperature of the water. We can
solve this task when we gave each fish a reference to its tank:
stefan@AMD64X2 ~/pet $ cat fish_tank.rb
class Fish
def initialize(name, favorite_temperature, tank)
@tank = tank
@n = name
@t = favorite_temperature
end
def tell_state
if @tank.temperature < @t
puts 'I feel cold'
elsif @tank.temperature = @t
puts 'I feel well'
else
puts 'I feel hot'
end
end
end
class Tank
attr_accessor :fish
attr_reader :temperature
def initialize(temperature)
@temperature = temperature
@fish = Array.new
end
end
t1 = Tank.new(18)
f1 = Fish.new('Ruby', 21, t1)
t1.fish << f1
t1.fish.each{|f| f.tell_state}
I am more familiar with a situation, where the tank is a module, so the
fish can access module variables. But now we really need many tanks,
each with very many fishes. Currently it seems to be a bit strange
giving each of thousands fishes a reference to its tank. Another
solution may be to give the .tell_state() function a tank parameter each
time when we call it. (A tank-temperature parameter is not a good idea,
because we may need more, light, food...)
(For my real application the tanks are windows, and fishes are graphical
elements in each window, see
http://www.ssalewski.de/PetEd-Demo.html.en)
Do I miss something?
Best regards,
Stefan Salewski
[toc] | [next] | [standalone]
| From | Josh Cheek <josh.cheek@gmail.com> |
|---|---|
| Date | 2011-05-05 14:47 -0500 |
| Message-ID | <BANLkTimHMoCwd694eS+7+toqn105B7fJAg@mail.gmail.com> |
| In reply to | #4006 |
[Note: parts of this message were removed to make it a legal post.]
On Thu, May 5, 2011 at 2:06 PM, Stefan Salewski <mail@ssalewski.de> wrote:
> I am working on a larger Ruby program, where instance variables of one
> class need access to content of another class -- I wonder how I should
> solve this problem best.
>
> Assume we have multiple fish tanks, each with multiple fishes. The
> fishes should tell us if they like the temperature of the water. We can
> solve this task when we gave each fish a reference to its tank:
>
> stefan@AMD64X2 ~/pet $ cat fish_tank.rb
> class Fish
> def initialize(name, favorite_temperature, tank)
> @tank = tank
> @n = name
> @t = favorite_temperature
> end
> def tell_state
> if @tank.temperature < @t
> puts 'I feel cold'
> elsif @tank.temperature = @t
> puts 'I feel well'
> else
> puts 'I feel hot'
> end
> end
> end
>
> class Tank
> attr_accessor :fish
> attr_reader :temperature
> def initialize(temperature)
> @temperature = temperature
> @fish = Array.new
> end
> end
>
> t1 = Tank.new(18)
> f1 = Fish.new('Ruby', 21, t1)
> t1.fish << f1
> t1.fish.each{|f| f.tell_state}
>
> I am more familiar with a situation, where the tank is a module, so the
> fish can access module variables. But now we really need many tanks,
> each with very many fishes. Currently it seems to be a bit strange
> giving each of thousands fishes a reference to its tank. Another
> solution may be to give the .tell_state() function a tank parameter each
> time when we call it. (A tank-temperature parameter is not a good idea,
> because we may need more, light, food...)
>
> (For my real application the tanks are windows, and fishes are graphical
> elements in each window, see
> http://www.ssalewski.de/PetEd-Demo.html.en)
>
> Do I miss something?
>
> Best regards,
>
> Stefan Salewski
>
>
>
>
Great question! It's especially important when the fish / tank start
affecting each other, ie cold tank takes away 10 life units from the fish,
should the tank do this to the fish, or should the fish look at the tank and
do it to itself? If it should be the fish, then what if it only happens
during certain tank conditions such as proximity to other fish? So maybe it
should be the tank doing this task, but what if the fish is feeling friendly
that day, and can tolerate proximity to other fish? They are so dependent on
each other, who is responsible for what, and how should that relationship be
established?
I'm eager to see responses to this, I've run into the same issue in the
past, and was never satisfied with my solutions.
[toc] | [prev] | [next] | [standalone]
| From | Johannes Held <johannes.held@informatik.uni-erlangen.de> |
|---|---|
| Date | 2011-05-06 10:23 +0200 |
| Message-ID | <92hpeiFe2mU1@mid.dfncis.de> |
| In reply to | #4006 |
On 05.05.2011 21:06, Stefan Salewski wrote: > But now we really need many tanks, each with very many fishes. > Currently it seems to be a bit strange giving each of thousands > fishes a reference to its tank. You can control the fishes within the tank. Every fish is saved in an array in tank. The tank queries every fish for it's mood … http://pastie.org/1870880 > Another solution may be to give the .tell_state() function a tank > parameter each time when we call it. (A tank-temperature parameter > is not a good idea, because we may need more, light, food...) Why not? Pass them via a hash? IMO there's no need for a fish to know its tank. -- Johannes
[toc] | [prev] | [next] | [standalone]
| From | Stefan Salewski <mail@ssalewski.de> |
|---|---|
| Date | 2011-05-07 16:27 -0500 |
| Message-ID | <1304803573.3606.7.camel@AMD64X2.fritz.box> |
| In reply to | #4026 |
On Fri, 2011-05-06 at 17:25 +0900, Johannes Held wrote:
> On 05.05.2011 21:06, Stefan Salewski wrote:
> > But now we really need many tanks, each with very many fishes.
> > Currently it seems to be a bit strange giving each of thousands
> > fishes a reference to its tank.
> You can control the fishes within the tank. Every fish is saved in an
> array in tank. The tank queries every fish for it's mood …
>
> http://pastie.org/1870880
>
> > Another solution may be to give the .tell_state() function a tank
> > parameter each time when we call it. (A tank-temperature parameter
> > is not a good idea, because we may need more, light, food...)
> Why not? Pass them via a hash?
> IMO there's no need for a fish to know its tank.
>
>
> --
> Johannes
>
Thank you for your example.
Of course this is a way to solve the problem. It may look not very
natural, that we have to tell the fish the parameters of its tank, when
we ask the fish about its mood:
>mood = fish.tell_mood({:temp => t.temp, :food => t.food_type})
But OK, this is the way to do it. Now I know that I have not missed
something.
Thanks
Stefan Salewski
[toc] | [prev] | [next] | [standalone]
| From | Hassan Schroeder <hassan.schroeder@gmail.com> |
|---|---|
| Date | 2011-05-07 18:27 -0500 |
| Message-ID | <BANLkTi=gnqqw1R2ni_7yez9i2pLqmJk_jA@mail.gmail.com> |
| In reply to | #4077 |
2011/5/7 Stefan Salewski <mail@ssalewski.de>:
>
> Of course this is a way to solve the problem. It may look not very
> natural, that we have to tell the fish the parameters of its tank, when
> we ask the fish about its mood:
>
>>mood = fish.tell_mood({:temp => t.temp, :food => t.food_type})
>
> But OK, this is the way to do it. Now I know that I have not missed
> something.
A little late to this, but isn't this a good case for the Observer pattern?
So the fish are always "aware" of the tank environment? Very simply:
-----------------------------
require 'observer'
class Tank
include Observable
def temperature
@temperature
end
def temperature=(temperature)
@temperature = temperature
changed
notify_observers(temperature)
end
end
class Fish
attr_accessor :tank_temperature
def initialize(tank)
@tank_temperature = tank.temperature
tank.add_observer(self)
end
def update(temperature)
puts "temperature changed to #{temperature}"
@tank_temperature = temperature
end
end
-----------------------------
And exercise with:
-----------------------------
require 'tank'
require 'fish'
tank = Tank.new
tank.temperature= 100
fish = Fish.new(tank)
puts "fish.tank_temperature: #{fish.tank_temperature}" # => 100
tank.temperature= 102
puts "fish.tank_temperature: #{fish.tank_temperature}" # => 102
-----------------------------
FWIW,
--
Hassan Schroeder ------------------------ hassan.schroeder@gmail.com
twitter: @hassan
[toc] | [prev] | [next] | [standalone]
| From | John Feminella <johnf@bitsbuilder.com> |
|---|---|
| Date | 2011-05-07 18:36 -0500 |
| Message-ID | <BANLkTinK58ienqpmGLXU=y1MJehug=7s2g@mail.gmail.com> |
| In reply to | #4086 |
You add fish to a tank, not tanks to a fish. An alternative proposal,
that doesn't involve Fish holding a reference to Tanks at all:
class Fish
# ...
def comfortable?(temp_in_degrees_celsius)
(@min..@max).include? temp_in_degrees_celsius
end
end
class Tank
# ...
def add_inhabitant(i)
self.inhabitants << i
end
def update
# ...
# possible temperature change!
self.inhabitants.each do |inhabitant|
logger.warn("#{inhabitant} is experiencing environmental
stress") unless inhabitant.comfortable?(t)
end
end
end
--
John Feminella
Principal Consultant, BitsBuilder
LI: http://www.linkedin.com/in/johnxf
SO: http://stackoverflow.com/users/75170/
On Sat, May 7, 2011 at 19:27, Hassan Schroeder
<hassan.schroeder@gmail.com> wrote:
> 2011/5/7 Stefan Salewski <mail@ssalewski.de>:
>>
>> Of course this is a way to solve the problem. It may look not very
>> natural, that we have to tell the fish the parameters of its tank, when
>> we ask the fish about its mood:
>>
>>>mood = fish.tell_mood({:temp => t.temp, :food => t.food_type})
>>
>> But OK, this is the way to do it. Now I know that I have not missed
>> something.
>
> A little late to this, but isn't this a good case for the Observer pattern?
> So the fish are always "aware" of the tank environment? Very simply:
>
> -----------------------------
> require 'observer'
>
> class Tank
> include Observable
>
> def temperature
> @temperature
> end
>
> def temperature=(temperature)
> @temperature = temperature
> changed
> notify_observers(temperature)
> end
>
> end
>
> class Fish
>
> attr_accessor :tank_temperature
>
> def initialize(tank)
> @tank_temperature = tank.temperature
> tank.add_observer(self)
> end
>
> def update(temperature)
> puts "temperature changed to #{temperature}"
> @tank_temperature = temperature
> end
>
> end
> -----------------------------
> And exercise with:
> -----------------------------
> require 'tank'
> require 'fish'
>
> tank = Tank.new
> tank.temperature= 100
> fish = Fish.new(tank)
> puts "fish.tank_temperature: #{fish.tank_temperature}" # => 100
>
> tank.temperature= 102
> puts "fish.tank_temperature: #{fish.tank_temperature}" # => 102
> -----------------------------
>
> FWIW,
> --
> Hassan Schroeder ------------------------ hassan.schroeder@gmail.com
> twitter: @hassan
>
>
[toc] | [prev] | [next] | [standalone]
| From | Hassan Schroeder <hassan.schroeder@gmail.com> |
|---|---|
| Date | 2011-05-07 19:31 -0500 |
| Message-ID | <BANLkTimNdfvMFUC=YKwiWK1CyeGyiWoRng@mail.gmail.com> |
| In reply to | #4087 |
On Sat, May 7, 2011 at 4:36 PM, John Feminella <johnf@bitsbuilder.com> wrote: > You add fish to a tank, not tanks to a fish. POV - you could as well say you "assign" a tank to a particular fish :-) And actually, if I were implementing this myself, I'd probably separate the Tank from the Environment it provides and have the Fish observe its environment. As always, YMMV. -- Hassan Schroeder ------------------------ hassan.schroeder@gmail.com twitter: @hassan
[toc] | [prev] | [next] | [standalone]
| From | John Feminella <johnf@bitsbuilder.com> |
|---|---|
| Date | 2011-05-07 19:51 -0500 |
| Message-ID | <BANLkTi=KZHOy69=CiNe=Z+yuBdw3eUYfQw@mail.gmail.com> |
| In reply to | #4091 |
>> You add fish to a tank, not tanks to a fish. > > POV - you could as well say you "assign" a tank to a particular fish :-) Perhaps, but in this model, at least, the fish can't exist without the tank, while the same is not true of a tank without the fish. So that's a strong motivation for considering putting fish in a tank, rather than the other way around. > And actually, if I were implementing this myself, I'd probably separate > the Tank from the Environment it provides and have the Fish observe > its environment. There's lots of ways to skin this cat (as there are with pretty much any software problem). I was just picking what I thought was the STTCPW. ~ jf -- John Feminella Principal Consultant, BitsBuilder LI: http://www.linkedin.com/in/johnxf SO: http://stackoverflow.com/users/75170/ On Sat, May 7, 2011 at 20:31, Hassan Schroeder <hassan.schroeder@gmail.com> wrote: > On Sat, May 7, 2011 at 4:36 PM, John Feminella <johnf@bitsbuilder.com> wrote: >> You add fish to a tank, not tanks to a fish. > > POV - you could as well say you "assign" a tank to a particular fish :-) > > And actually, if I were implementing this myself, I'd probably separate > the Tank from the Environment it provides and have the Fish observe > its environment. > > As always, YMMV. > -- > Hassan Schroeder ------------------------ hassan.schroeder@gmail.com > twitter: @hassan > >
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.ruby
csiph-web