Forum: Ruby simple ruby language question

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
unknown (Guest)
on 2006-03-19 21:13
(Received via mailing list)
ok, i've got some module and it has some instance variables i want to
be set by the classes extending the module, and aparently i'm not doing
this correctly:


module A
  def test
    raise 'ARG' if !@blah
    @blah
  end
end

class B
  include A
  extend A
  @blah = 'YES!'
end



irb(main):025:0> b = B.new
=> #<B:0x136376c>
irb(main):026:0> b.test
RuntimeError: ARG
        from (irb):9:in `test'
        from (irb):26


can anyone tell me what the syntax should be? how do i set @blah in the
B class so that its available to the test method
unknown (Guest)
on 2006-03-19 21:39
(Received via mailing list)
Hi --

On Mon, 20 Mar 2006, removed_email_address@domain.invalid wrote:

> end
> => #<B:0x136376c>
> irb(main):026:0> b.test
> RuntimeError: ARG
>        from (irb):9:in `test'
>        from (irb):26
>
>
> can anyone tell me what the syntax should be? how do i set @blah in the
> B class so that its available to the test method

When using instance variables, you have to match each one precisely to
the object whose instance variable it is.  The @blah in @blah = 'YES!'
belongs to the class object B.  The @blah inside test belongs (or will
belong, upon execution) to whatever object is calling "test".  Unless
that object is the class object B, its @blah will be different (even
if it's an instance of B).

So if you want them to match up, you have to call test on the class
object B:

   B.test

That will run "test" with B as the receiver, so you'll see B's
instance variable @blah.  (By the way, it's a good idea not to name
your test methods "test", because there's already a method with that
name in Kernel, so sometimes you'll get behavior you don't expect.
That's not the issue here, though.)


David

--
David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light, LLC (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! http://www.manning.com/books/black
Scott (Guest)
on 2006-03-19 22:43
(Received via mailing list)
In class B, you are attepmting to use an instance variable as if it
were a class variable.  To set @blah to a value when its instantiated,
you'll need to stick that line in the constructor:

class B
  include A
  extend A

  def initialize
    @blah = 'YES!'
  end
end

Also, you dont need to both include and extend A inside B.  Use extend
when you want to use the modules methods as class methods:

module X
  def classy
    puts "Yup, I'm classy"
  end
end

class Y
  extend X
end

Y.classy
=>  Yup, I'm classy

You can also extend an instance of an object:

s = "Holy shniekes"
s.extend(X)
s.classy
=>  Yup, I'm classy

Use include when you want to "mix-in" the modules methods with the
instance methods defined in the class:

module X
  def classy
    puts "Yup, I'm classy"
  end
end

class Y
  include X
end

Y.new.classy
=>  Yup, I'm classy

Hope that helps :)

- Scott
Marcin MielżyÅ?ski (Guest)
on 2006-03-20 00:03
(Received via mailing list)
removed_email_address@domain.invalid wrote:
> end
> => #<B:0x136376c>
> irb(main):026:0> b.test
> RuntimeError: ARG
>         from (irb):9:in `test'
>         from (irb):26
>
>
> can anyone tell me what the syntax should be? how do i set @blah in the
> B class so that its available to the test method
>

Try this one:

module A
   def test
     raise 'ARG' if !@blah
     @blah
   end
end

class B
   include A

   def initialize
     @blah = 'YES!'
   end
end

b = B.new
p b.test

Module#include will make module methods to become instance ones.
Object#extend adds methods to an instance (to the class B in this case,
you could say then B.test)

consider also:

class A
     @a=4
end

p A.class_eval{@a}
=> 4

which means that @a is an instance variable of class object, not an
instance variable of class instance.


lopex
Marcin MielżyÅ?ski (Guest)
on 2006-03-20 00:08
(Received via mailing list)
Marcin MielżyÅ?ski wrote:

It can be easily seen who is the default receiver (class object or
instance object) by doing this:


class A
     p self

     def initialize
         p self
     end
end

A.new


lopex
Robert K. (Guest)
on 2006-03-20 10:54
(Received via mailing list)
Marcin MielżyÅ?ski wrote:
>   def initialize
>     @blah = 'YES!'
>   end
> end
>
> b = B.new
> p b.test

You can even automate this with proper use of initializers:

module A
   def initialize(*a,&b)
     super
     @blah = "set"
   end

   def test
     raise 'ARG' if !@blah
     @blah
   end
end

class B
   include A
end

class C
   include A

   def initialize(x)
     super()
     @another_member = x
   end
end

 >> B.new.test
=> "set"
 >> C.new(1).test
=> "set"

> Module#include will make module methods to become instance ones.
> Object#extend adds methods to an instance (to the class B in this case,
> you could say then B.test)

Adding to that, usually the OP should decide whether to do one or
another.

Kind regards

	robert
This topic is locked and can not be replied to.