[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

automatically call function on attribute set

Joe Laughlin

11/10/2004 6:00:00 PM

I have a class that represents an airplane. This class has a bunch of data
members: x/y/z positions, x/y/z velocities, pitches, rolls, etc. What I did
is let the user configure what different attributes the airplane had in a
YAML config file, then have the airplane class read in that file and setup
attr_accessors for each attribute in the file.

I have another object (call it airplane_drawing) that is responsible for
drawing this airplane on the screen. It needs to have access to some of the
attributes of the airplane, and it needs have some of its own attributes
changed whenever airplane's attributes changes.

What is the best way to get airplane_drawing to be notified whenever some
attribute of airplane is changed? Should I have a thread (or similar) that
checks the airplane object to see if anything's changed?

I hope I've explained this well enough for people to understand... I feel
like this is a fairly common thing to do, but I'm not sure of the best way
to do it.

Thanks,
Joe


26 Answers

Ara.T.Howard

11/10/2004 6:32:00 PM

0

Michael Neumann

11/10/2004 7:24:00 PM

0

On Thu, Nov 11, 2004 at 03:13:30AM +0900, Joe Laughlin wrote:
> I have a class that represents an airplane. This class has a bunch of data
> members: x/y/z positions, x/y/z velocities, pitches, rolls, etc. What I did
> is let the user configure what different attributes the airplane had in a
> YAML config file, then have the airplane class read in that file and setup
> attr_accessors for each attribute in the file.
>
> I have another object (call it airplane_drawing) that is responsible for
> drawing this airplane on the screen. It needs to have access to some of the
> attributes of the airplane, and it needs have some of its own attributes
> changed whenever airplane's attributes changes.
>
> What is the best way to get airplane_drawing to be notified whenever some
> attribute of airplane is changed? Should I have a thread (or similar) that
> checks the airplane object to see if anything's changed?

You should use an Observer.

require 'observer'

class Airplane
include Observable

def initialize
@x = 0
end

def fly
# airplane changes it's coordinate
@x += 10

changed
notify_observers(self)
end
end

class AirplaneDrawing
def update(obj)
# ...
end
end

airbus = Airplane.new
drawing = AirplaneDrawing.new
airbus.add_observer(drawing)
airbus.fly

Regards,

Michael


Joel VanderWerf

11/10/2004 9:03:00 PM

0

Joe Laughlin wrote:
> I have a class that represents an airplane. This class has a bunch of data
> members: x/y/z positions, x/y/z velocities, pitches, rolls, etc. What I did
> is let the user configure what different attributes the airplane had in a
> YAML config file, then have the airplane class read in that file and setup
> attr_accessors for each attribute in the file.
>
> I have another object (call it airplane_drawing) that is responsible for
> drawing this airplane on the screen. It needs to have access to some of the
> attributes of the airplane, and it needs have some of its own attributes
> changed whenever airplane's attributes changes.
>
> What is the best way to get airplane_drawing to be notified whenever some
> attribute of airplane is changed? Should I have a thread (or similar) that
> checks the airplane object to see if anything's changed?
>
> I hope I've explained this well enough for people to understand... I feel
> like this is a fairly common thing to do, but I'm not sure of the best way
> to do it.

Another approach is the observable lib on RAA
(http://raa.ruby-lang.org/list.rhtml?name=...).


require 'observable'

class Airplane
extend Observable

observable :x, :y, :z

def initialize(x = 0, y = 0, z = 0)
@x, @y, @z = x, y, z
end

def fly
self.x += 1 # don't use @x=, or else no notification
end
end

class Drawing
def initialize(airplane)
airplane.when_x do
puts "moving in x dimension to #{airplane.x}"
end
end
end

airplane = Airplane.new
drawing = Drawing.new(airplane) # ==> moving in x dimension to 0
airplane.fly # ==> moving in x dimension to 1
airplane.fly # ==> moving in x dimension to 2


The observer.rb in the standard library is better if you want more
control over sending the notification. For example, if x,y,z all change,
but you only want to send the notification once for all three. (Or you
could use an attribute that contains the whole x,y,z point, and make
that observable.)


Van Dyk, Joe

11/11/2004 6:53:00 PM

0

Joe Laughlin wrote:
> I have a class that represents an airplane. This class
> has a bunch of data members: x/y/z positions, x/y/z
> velocities, pitches, rolls, etc. What I did is let the
> user configure what different attributes the airplane had
> in a YAML config file, then have the airplane class read
> in that file and setup attr_accessors for each attribute
> in the file.
>
> I have another object (call it airplane_drawing) that is
> responsible for drawing this airplane on the screen. It
> needs to have access to some of the attributes of the
> airplane, and it needs have some of its own attributes
> changed whenever airplane's attributes changes.
>
> What is the best way to get airplane_drawing to be
> notified whenever some attribute of airplane is changed?
> Should I have a thread (or similar) that checks the
> airplane object to see if anything's changed?
>
> I hope I've explained this well enough for people to
> understand... I feel like this is a fairly common thing
> to do, but I'm not sure of the best way to do it.
>
> Thanks,
> Joe

Aha! Thanks for the response you guys. I knew that there was a pattern
that would help me, but I just couldn't think of it.


Van Dyk, Joe

11/11/2004 6:56:00 PM

0

Joel VanderWerf wrote:
> Joe Laughlin wrote:
>> I have a class that represents an airplane. This class
>> has a bunch of data members: x/y/z positions, x/y/z
>> velocities, pitches, rolls, etc. What I did is let the
>> user configure what different attributes the airplane
>> had in a YAML config file, then have the airplane class
>> read in that file and setup attr_accessors for each
>> attribute in the file.
>>
>> I have another object (call it airplane_drawing) that is
>> responsible for drawing this airplane on the screen. It
>> needs to have access to some of the attributes of the
>> airplane, and it needs have some of its own attributes
>> changed whenever airplane's attributes changes.
>>
>> What is the best way to get airplane_drawing to be
>> notified whenever some attribute of airplane is changed?
>> Should I have a thread (or similar) that checks the
>> airplane object to see if anything's changed?
>>
>> I hope I've explained this well enough for people to
>> understand... I feel like this is a fairly common thing
>> to do, but I'm not sure of the best way to do it.
>
> Another approach is the observable lib on RAA
> (http://raa.ruby-lang.org/list.rhtml?name=...).
>
>
> require 'observable'
>
> class Airplane
> extend Observable
>
> observable :x, :y, :z
>
> def initialize(x = 0, y = 0, z = 0)
> @x, @y, @z = x, y, z
> end
>
> def fly
> self.x += 1 # don't use @x=, or else no
> notification end
> end
>

What is the difference between self.x and @x?

Thanks,
Joe



Jacob Fugal

11/11/2004 7:39:00 PM

0

On Fri, 12 Nov 2004 04:13:30 +0900, Joe Van Dyk <joe.vandyk@boeing.com> wrote:
>
> What is the difference between self.x and @x?

self.x, sends either the :x or :x= method to self, depending if it's
an lvalue or rvalue respectively. @x just reads/writes to the instance
variable directly. If you're just using attr_accessor :x, they're the
same thing, but if you have, for instance:

class Foo
def bar
raise "@bar and @baz out of sync" unless @bar == @baz
@bar
end
def bar=( new_bar )
puts "setting @bar and @baz"
@bar = @baz = new_bar
end
def test1
self.bar = "test1"
end
def test2
@bar = "test2"
end
end

foo = Foo.new
foo.bar = "test"
# => setting @bar and @baz

puts foo.bar
# => test

foo.test1
# => setting @bar and @baz

puts foo.bar
# => test1

foo.test2
puts foo.bar
# RuntimeError: @bar and @baz out of sync

Using self.bar= keeps @bar and @baz in sync, while setting @bar
directly doesn't update @baz. Generally, if you have non-trivial
accessors for instance variables, you should use them even inside the
object rather than accessing the instance variables directly. I
usually use them even if the accessor is trivial, so that if the
accessor becomes non-trivial later I don't have to go find and fix all
the places where the instance variables are currently accessed
directly.

Jacob Fugal


Joel VanderWerf

11/11/2004 7:43:00 PM

0

Joe Van Dyk wrote:
> Joel VanderWerf wrote:
>
>> def fly
>> self.x += 1 # don't use @x=, or else no
>> notification end
>> end
>>
>
>
> What is the difference between self.x and @x?

In ruby, assigning to an instance variable @x like

@x += 1

does not invoke any methods (except the + method of the Integer class,
in this case). So there's no way for the Airplane class to detect the
assignment and (in this case) notify observers.

By contrast, the code

self.x += 1

forces a call to the method "x=", which has been defined by "observable
:x" to both set the value of @x and to notify observers.

And just for completeness, the code

x += 1

can only assign to a local variable, even if "x=" has been defined as a
method.




Van Dyk, Joe

11/12/2004 7:50:00 PM

0


"Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> wrote in message
news:4193C096.7070007@path.berkeley.edu...
> Joe Van Dyk wrote:
> > Joel VanderWerf wrote:
> >
> >> def fly
> >> self.x += 1 # don't use @x=, or else no
> >> notification end
> >> end
> >>
> >
> >
> > What is the difference between self.x and @x?
>
> In ruby, assigning to an instance variable @x like
>
> @x += 1
>
> does not invoke any methods (except the + method of the Integer class,
> in this case). So there's no way for the Airplane class to detect the
> assignment and (in this case) notify observers.
>
> By contrast, the code
>
> self.x += 1
>
> forces a call to the method "x=", which has been defined by "observable
> :x" to both set the value of @x and to notify observers.
>
> And just for completeness, the code
>
> x += 1
>
> can only assign to a local variable, even if "x=" has been defined as a
> method.
>
>

Ok. In general, it's best to use self.x as opposed to @x?


Joel VanderWerf

11/12/2004 9:20:00 PM

0

Joe Van Dyk wrote:
> "Joel VanderWerf" <vjoel@PATH.Berkeley.EDU> wrote in message
> news:4193C096.7070007@path.berkeley.edu...
>
>>Joe Van Dyk wrote:
>>
>>>Joel VanderWerf wrote:
>>>
>>>
>>>> def fly
>>>> self.x += 1 # don't use @x=, or else no
>>>> notification end
>>>> end
>>>>
>>>
>>>
>>>What is the difference between self.x and @x?
>>
>>In ruby, assigning to an instance variable @x like
>>
>> @x += 1
>>
>>does not invoke any methods (except the + method of the Integer class,
>>in this case). So there's no way for the Airplane class to detect the
>>assignment and (in this case) notify observers.
>>
>>By contrast, the code
>>
>> self.x += 1
>>
>>forces a call to the method "x=", which has been defined by "observable
>>:x" to both set the value of @x and to notify observers.
>>
>>And just for completeness, the code
>>
>> x += 1
>>
>>can only assign to a local variable, even if "x=" has been defined as a
>>method.
>>
>>
>
>
> Ok. In general, it's best to use self.x as opposed to @x?

Depends. I tend to use @x as rarely as possible, so that subclasses can,
if necessary, define methods that get/set the value in some other way.
Or if I later decide that the class itself needs to do something else
and not just go directly to the instance variable (for instance, logging
code). But accessing @x is faster than sending the #x method to self.


Denis Beauregard

9/15/2009 3:31:00 AM

0

Le Mon, 14 Sep 2009 23:22:44 -0400, "ti-coune" <ti.coune@alinto.comX>
?crivait dans soc.culture.quebec:

>
>"Couillu" <couillu@qc.com> a ?crit dans le message de news:
>mn.74f67d99fd5151a8.85165@qc.com...
>> Maudite maladie ? marde.
>
>
>C'est qui Patrick Swayze?

Un acteur. Danse lascive et Ghost/Mon fant?me d'amour.

http://fr.wikipedia.org/wiki/Patr...
Cette biographie est un exploit car on y trouve sa date de d?c?s...


Denis