Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.ruby > #4006 > unrolled thread

Cross access between instance variables

Started byStefan Salewski <mail@ssalewski.de>
First post2011-05-05 14:06 -0500
Last post2011-05-07 19:51 -0500
Articles 8 — 5 participants

Back to article view | Back to comp.lang.ruby


Contents

  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

#4006 — Cross access between instance variables

FromStefan Salewski <mail@ssalewski.de>
Date2011-05-05 14:06 -0500
SubjectCross 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]


#4008

FromJosh Cheek <josh.cheek@gmail.com>
Date2011-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]


#4026

FromJohannes Held <johannes.held@informatik.uni-erlangen.de>
Date2011-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]


#4077

FromStefan Salewski <mail@ssalewski.de>
Date2011-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]


#4086

FromHassan Schroeder <hassan.schroeder@gmail.com>
Date2011-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]


#4087

FromJohn Feminella <johnf@bitsbuilder.com>
Date2011-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]


#4091

FromHassan Schroeder <hassan.schroeder@gmail.com>
Date2011-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]


#4092

FromJohn Feminella <johnf@bitsbuilder.com>
Date2011-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