Class atrr_accessor

  • Thread starter Oliver Saunders
  • Start date
O

Oliver Saunders

Why does this not work?
TypeError: Foo is not a class
from (irb):19


I understand that the class << self idiom can be used to work around
this problem but I would like to understand why the above triggers such
an error and what is meant by it.

Thanks.
 
T

Trans

Why does this not work?

An ideology?
TypeError: Foo is not a class
=A0 =A0 =A0 =A0 from (irb):19

class Module
public :attr_accessor
end

All fixed.
I understand that the class << self idiom can be used to work around
this problem but I would like to understand why the above triggers such
an error and what is meant by it.

Well, I think the idea is that you shouldn't be changing a class'
interface from the "outside" ie. so willy-nilly. So you are required
to go "inside" to get the job done. Sort of a caution barrier. But it
does suck that this requires a second layer, eg. class << self, to get
there. I have tried a private #meta method in the past.

class Foo
meta.attr_accessor :baz
end

which works, though I'm not sure the term "meta" feels quite right.
I've avoided ever using it though because I know others would look at
it and think "what?".

T.
 
T

The Higgs bozo

Oliver said:
Why does this not work?

TypeError: Foo is not a class
from (irb):19

You must have miscopied your error message. I obtain

NoMethodError: private method `attr_accessor' called for Class:Class

attr_accessor is a private method of Module, and as such cannot be
called directly with the dot notation. You can call it with send(), or
like this:

class Foo
self.class.instance_eval { attr_accessor :baz }
end

But nevermind, because this is not what you want!

Foo.baz = :qux
p Foo.baz # => :qux

class Bar
end

Bar.baz = 4
p Bar.baz # => 4

You've just added methods #baz and #baz= to every class. This is
because

class Foo
p(self.class == Class) # => true
end

You want the self << class construct that you mentioned, which is the
singleton class,

class Foo
class << self
attr_accessor :baz
end
end

When you said self.class, you were calling Object#class which tells you
the birth canal of an object. But many things can happen after birth,
and kids can end up really different from their parents! This
difference is described in the singleton class. It's unique to the
object. Above, we are adding a method to Foo's singleton class.

BTW there's nothing special about "class << self". You could also say,

class Foo
end
class << Foo
attr_accessor :baz
end

which is the same thing. "class << x" grabs the singleton class of x.

Hope this helps.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,186
Messages
2,570,998
Members
47,587
Latest member
JohnetteTa

Latest Threads

Top