Class_attr_accessor

I was playing around with class variables and class instance variables because I wanted to implement a certain functionality, while not really understanding the coexistence of the two, I found the reason the two exist is quite clear, the class instance variables facilitate "subclass slots" (as I know them from other languages) while the @@ syntax facilitates "class slots"

I did a google search for "class_attr_accessor" and found that a number of people have implemented this functionality in their own code. I suggest it be officially added to the ruby distribution.

Here is an example:

class Module
  private
  def class_attr_accessor(*attrs)
    attrs.each {|attr|
      module_eval(<<-EOS)
        class << self
          def #{attr}; @#{attr}; end
          def #{attr}=(v); @#{attr} = v; end
        end
      EOS
    }
  end
end

I really don't think a new notation, similar to @@, is necessary, I think calling obj.class.accessor_name is very nice. In fact having both a subclass_attr_accessor and a class_attr_accessor wouldn't hurt either. In that case, class_attr_accessor would just be a way to make @@vars public.

-Jeff Moss

check out

   http://raa.ruby-lang.org/project/traits/

inheritence is quite tricky with the impl of class_attr_accessor above.

cheers.

-a

···

On Tue, 12 Jul 2005, Jeffrey Moss wrote:

I was playing around with class variables and class instance variables because I wanted to implement a certain functionality, while not really understanding the coexistence of the two, I found the reason the two exist is quite clear, the class instance variables facilitate "subclass slots" (as I know them from other languages) while the @@ syntax facilitates "class slots"

I did a google search for "class_attr_accessor" and found that a number of people have implemented this functionality in their own code. I suggest it be officially added to the ruby distribution.

Here is an example:

class Module
private
def class_attr_accessor(*attrs)
  attrs.each {|attr|
    module_eval(<<-EOS)
      class << self
        def #{attr}; @#{attr}; end
        def #{attr}=(v); @#{attr} = v; end
      end
    EOS
  }
end

I really don't think a new notation, similar to @@, is necessary, I think calling obj.class.accessor_name is very nice. In fact having both a subclass_attr_accessor and a class_attr_accessor wouldn't hurt either. In that case, class_attr_accessor would just be a way to make @@vars public.

-Jeff Moss

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

David,

To clarify, what I meant by a subclass slot is accessors that point to a new class instance variable in *each* subclasses, whereas a class slot points to the instance varaible in the class that the class slot was defined in.

Here is an example to illustrate:

class A
  subclass_attr_accessor :subclass_slot
  class_attr_accessor :class_slot
end

class B < A; end

class C < A; end

b = B.new
c = C.new

b.class.subclass_slot = 1
b.class.class_slot = 2

p c.class.subclass_slot # nil
p c.class.class_slot # 2

c.class.subclass_slot = 3
p b.class.subclass_slot # 1

bb = B.new
p bb.subclass_slot # 1

-Jeff

···

----- Original Message ----- From: "David A. Black" <dblack@wobblini.net>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Monday, July 11, 2005 4:27 PM
Subject: Re: class_attr_accessor

Hi --

On Tue, 12 Jul 2005, Jeffrey Moss wrote:

I was playing around with class variables and class instance variables because I wanted to implement a certain functionality, while not really understanding the coexistence of the two, I found the reason the two exist is quite clear, the class instance variables facilitate "subclass slots" (as I know them from other languages) while the @@ syntax facilitates "class slots"

I'm not sure what you mean (but I'm not familiar with the term
"subclass slot"). If a class object has instance variables, there are
no implications for the subclasses:

  class A
    @x = 1
  end

  class B < A
    p instance_variables #
  end

This is really just because instance variables are per-object, so the instance variables belonging to the object A are of no concern to
any other object (including B). But, again, I'm not sure I'm getting
what you meant about subclasses.

I did a google search for "class_attr_accessor" and found that a number of people have implemented this functionality in their own code. I suggest it be officially added to the ruby distribution.

Here is an example:

class Module
private
def class_attr_accessor(*attrs)
  attrs.each {|attr|
    module_eval(<<-EOS)
      class << self
        def #{attr}; @#{attr}; end
        def #{attr}=(v); @#{attr} = v; end
      end
    EOS
  }
end

I really don't think a new notation, similar to @@, is necessary, I think calling obj.class.accessor_name is very nice. In fact having both a subclass_attr_accessor and a class_attr_accessor wouldn't hurt either. In that case, class_attr_accessor would just be a way to make @@vars public.

I'm still not sure where subclasses come in; they're different
objects, so they have different instance variables. Also, class
variables (@@var) aren't part of the whole attr_* and instance
variable universe, so I don't think you'd want to have a method with
an attr_* name that dealt in class variables. It would just get
confusing.

Actually I would say not only is a new notation not necessary for
class instance variables, but a new method isn't either :slight_smile: What we
sometimes call "class instance variables" are not a separate
language-level construct. They are simply instance variables which
happen to belong to a Class object. The object (like any other
object) can choose to expose them, keep state in them, etc.

Consider these two examples:

   class C
     class << self
       attr_accessor :x
     end
   end

   some_string = "I am a string"
   class << some_string
     attr_accessor :y
   end

In both cases, I've created an accessor for an object. One is a Class
object (C); one is a String object (some_string). But I don't expect
there to be a class_attr_accessor or string_attr_accessor method. I
just get myself into the right scope (with the class keyword), and
then I call attr_accessor. Classes are not special cases in this
context.

In both cases, too, the accessors will be implemented using instance
variables (since that's how attr_* works). The fact that C is a Class
object does not change this, one way or the other: there's no
involvement of different variables (such as @@var), and there's no
*more* involvement of other objects (such as instances or subclasses
of C) than there is in cases where the object gettings accessorized is
not a Class.

I think it can be useful to use the term "class instance variable" in
cases where someone might mistakenly think that you're talking about
an instance variable of instances of a class, and you want to clarify
that that's not what you mean. But it's actually not a separate
construct, and attr_* works the same for Class objects as for other
objects. I would personally be opposed to introducing the appearance
of a difference into the language.

David

--
David A. Black
dblack@wobblini.net

I think it only gets tricky like you've pointed out if you're trying to do default variable initialization values, but on the other hand this is probably 99% of the useful purposes of a class_attr is with a default value set. So your point is well taken.

-Jeff

···

----- Original Message ----- From: "Ara.T.Howard" <Ara.T.Howard@noaa.gov>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Monday, July 11, 2005 4:06 PM
Subject: Re: class_attr_accessor

On Tue, 12 Jul 2005, Jeffrey Moss wrote:

I was playing around with class variables and class instance variables because I wanted to implement a certain functionality, while not really understanding the coexistence of the two, I found the reason the two exist is quite clear, the class instance variables facilitate "subclass slots" (as I know them from other languages) while the @@ syntax facilitates "class slots"

I did a google search for "class_attr_accessor" and found that a number of people have implemented this functionality in their own code. I suggest it be officially added to the ruby distribution.

Here is an example:

class Module
private
def class_attr_accessor(*attrs)
  attrs.each {|attr|
    module_eval(<<-EOS)
      class << self
        def #{attr}; @#{attr}; end
        def #{attr}=(v); @#{attr} = v; end
      end
    EOS
  }
end

I really don't think a new notation, similar to @@, is necessary, I think calling obj.class.accessor_name is very nice. In fact having both a subclass_attr_accessor and a class_attr_accessor wouldn't hurt either. In that case, class_attr_accessor would just be a way to make @@vars public.

-Jeff Moss

check out

  http://raa.ruby-lang.org/project/traits/

inheritence is quite tricky with the impl of class_attr_accessor above.

cheers.

-a
--

> email :: ara [dot] t [dot] howard [at] noaa [dot] gov
> phone :: 303.497.6469
> My religion is very simple. My religion is kindness.
> --Tenzin Gyatso

Hi --

David,

To clarify, what I meant by a subclass slot is accessors that point to a new class instance variable in *each* subclasses, whereas a class slot points to the instance varaible in the class that the class slot was defined in.

Here is an example to illustrate:

class A
subclass_attr_accessor :subclass_slot
class_attr_accessor :class_slot
end

class B < A; end

class C < A; end

b = B.new
c = C.new

b.class.subclass_slot = 1
b.class.class_slot = 2

p c.class.subclass_slot # nil

It looks like subclass_slot does the same thing that happens now with
attr_accessor, right?

p c.class.class_slot # 2

I don't think "class_slot" is right here. Maybe "hierarchy_slot".
But then you're doing the hierarchy-scoped thing, which has been a
characteristic of class variables and which is slated to be changed in
2.0 (and possibly is in 1.9). If it's considered obsolescent for
class variables, which are a sort of hybrid construct anyway, I think it would be yet more out of character for anything in the attr_*
family, and/or anything involving instance variables. It's one thing
for subclasses to inherit the fact of having an accessor method; but
if they are actually able to change their parent's state (presumably
via an instance variable, ultimately), that breaks the per-object-ness
of instance variables.

That may be why Matz decided to have class variables step in and
provide per-hierarchy state. But, as above, that's supposed to be
eliminated.

c.class.subclass_slot = 3
p b.class.subclass_slot # 1

bb = B.new
p bb.subclass_slot # 1

You mean bb.class.subclass_slot, I assume?

David

···

On Tue, 12 Jul 2005, Jeffrey Moss wrote:

--
David A. Black
dblack@wobblini.net

right you are. it bit me a few times and was ending up writing things like

   class A
     class << self
       attr 'a'
       attr 'b'
       def init
         self.a = 42
         self.b = 'forty-two'
       end
       def inherited subklass
         subklass.init
         super
       end
     end
     self.init
   end

   class B < A
     self.b = 42.0
   end

all over the place.

which starts being kinda ugly. i found that i almost always wanted class
varibles to essentially call 'super' when not over-ridden - in otherwords to
get a reasonable value from the parent class - but this is not possible with
either @@vars or @vars without some trickery. so i wrote it once and called
it traits. :wink:

btw. one of the things i like most about traits is that combination
getter/setter reads so well for exactly the case of class inheritence/default
values:

   require 'traits'

   class Package
     class << self
       trait 'size' => 42
       trait 'weight' => 42
     end
   end

   class LightPackage
     weight 4.2
   end

   class HeavyPackage
     weight 420
   end

and this works like it looks - all still have size 42.

cheers.

-a

···

On Tue, 12 Jul 2005, Jeffrey Moss wrote:

I think it only gets tricky like you've pointed out if you're trying to do
default variable initialization values, but on the other hand this is
probably 99% of the useful purposes of a class_attr is with a default value
set. So your point is well taken.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

right you are. it bit me a few times and was ending up writing things like

   class A
     class << self
       attr 'a'
       attr 'b'
       def init
         self.a = 42
         self.b = 'forty-two'
       end
       def inherited subklass
         subklass.init
         super
       end
     end
     self.init
   end

   class B < A
     self.b = 42.0
   end

all over the place.

The whole '<< self' syntax still confuses me; considering how often I
could use code that's the equivalent of this, I should obviously learn
to understand it... The newer pickaxe book implies that a new "virtual"
class is created when using this syntax; is that true when operating on
Class instances? That is, if I do this, are there somehow two A
instances, one of them "virtual" and with the methods I've added? I
doubt it, but the book leaves it a bit unclear.

I'll begin switching all of my 'def Class.attr...' method defs to this.
:confused:

which starts being kinda ugly. i found that i almost always wanted class
varibles to essentially call 'super' when not over-ridden - in otherwords to
get a reasonable value from the parent class - but this is not possible with
either @@vars or @vars without some trickery. so i wrote it once and called
it traits. :wink:

Interesting; I use class instance variables all over the place --
literally in just about every Ruby project I do -- and I almost never
have subclasses inheret values from parent classes.

Just having a builtin simple class-equivalent to the attr methods would
be very useful to me, which I think was the point of the initial post.
I love how Ruby's classes are just normal objects, but the fact that I
have to manually define all of these attr_accessors for the classes
themselves gets pretty annoying.

I'll check into 'traits', but I don't think I can use it for this
project, since I have to mostly stick to libs that are part of the
standard library.

···

On Tue, 12 Jul 2005, Ara.T.Howard wrote:

--
We're not surrounded, we're in a target-rich environment!
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://config.sage.org

The @@class_var syntax is unique in that you can assign a value to a class and it is propogated down.

With class instance vars, class << self; attr_accessor :class_var; end this will only give you a "slot", you still have to populate the slot with something. So for a subclass to inherit values, it would need to have something populating the subclasses values each time the class is inherited presumably in the "inherited" method or manually as in Ara's "init" method. The same goes for an instance attribute, it needs to be initialized in the initialize method, presumably, you can't assign defaults with the attr_accessor method.

By my definition, a "slot" is something that holds data, a "accessor" is merely a way to access that slot. I get the term "slot" from the dylan programming language, but it probably was coined long ago.

-Jeff

···

----- Original Message ----- From: "Luke Kanies" <luke@madstop.com>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Monday, July 11, 2005 5:52 PM
Subject: Re: class_attr_accessor

On Tue, 12 Jul 2005, Ara.T.Howard wrote:

right you are. it bit me a few times and was ending up writing things like

   class A
     class << self
       attr 'a'
       attr 'b'
       def init
         self.a = 42
         self.b = 'forty-two'
       end
       def inherited subklass
         subklass.init
         super
       end
     end
     self.init
   end

   class B < A
     self.b = 42.0
   end

all over the place.

The whole '<< self' syntax still confuses me; considering how often I
could use code that's the equivalent of this, I should obviously learn
to understand it... The newer pickaxe book implies that a new "virtual"
class is created when using this syntax; is that true when operating on
Class instances? That is, if I do this, are there somehow two A
instances, one of them "virtual" and with the methods I've added? I
doubt it, but the book leaves it a bit unclear.

I'll begin switching all of my 'def Class.attr...' method defs to this.
:confused:

which starts being kinda ugly. i found that i almost always wanted class
varibles to essentially call 'super' when not over-ridden - in otherwords to
get a reasonable value from the parent class - but this is not possible with
either @@vars or @vars without some trickery. so i wrote it once and called
it traits. :wink:

Interesting; I use class instance variables all over the place --
literally in just about every Ruby project I do -- and I almost never
have subclasses inheret values from parent classes.

Just having a builtin simple class-equivalent to the attr methods would
be very useful to me, which I think was the point of the initial post.
I love how Ruby's classes are just normal objects, but the fact that I
have to manually define all of these attr_accessors for the classes
themselves gets pretty annoying.

I'll check into 'traits', but I don't think I can use it for this
project, since I have to mostly stick to libs that are part of the
standard library.

--
We're not surrounded, we're in a target-rich environment!
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://config.sage.org

right you are. it bit me a few times and was ending up writing things like

   class A
     class << self
       attr 'a'
       attr 'b'
       def init
         self.a = 42
         self.b = 'forty-two'
       end
       def inherited subklass
         subklass.init
         super
       end
     end
     self.init
   end

   class B < A
     self.b = 42.0
   end

all over the place.

The whole '<< self' syntax still confuses me; considering how often I could
use code that's the equivalent of this, I should obviously learn to
understand it...

it just ducks into the singleton class of whatever object you use it on. in
the case the object is a class and it just so happens that class methods are
singleton methods of classes so you end up defining class methods this way

The newer pickaxe book implies that a new "virtual" class is created when
using this syntax; is that true when operating on Class instances? That is,
if I do this, are there somehow two A instances, one of them "virtual" and
with the methods I've added? I doubt it, but the book leaves it a bit
unclear.

not really. every ruby object has it's own singleton class where one can add
methods for only that object:

   harp:~ > cat a.rb
   a = Array::new
   class << a
     def foobar
       42
     end
   end
   p a.foobar

   harp:~ > ruby a.rb
   42

using this construct in classes just so happens to work nicely since singleton
methods of classes are also know as 'class methods' for instances of that
class.

I'll begin switching all of my 'def Class.attr...' method defs to this. > :confused:

there's no need really - but it allows you to do things like this that cannot
be done otherwise:

   class C
     class << self
       attr 'a'
       attr 'b'
       alias c a
       alias d b
     end
     attr 'a'
     attr 'b'
   end

so now we have instance method 'a' and 'b' and class methods 'a' and 'b' and
aliases for those two class methods 'c' and 'd' respectively. because the
'attr' and 'alias' calls are in class singleton scope here it works.

Interesting; I use class instance variables all over the place -- literally
in just about every Ruby project I do -- and I almost never have subclasses
inheret values from parent classes.

if they don't it's doubtful that they are real subclasses. most OO theory
would suggest that any subclass (subtype) is a specialzation only of the
base class - eg it should only ADD new behaviour. be definition that means
any existing class vars should be inherited. if you aren't inheriting class
vars (and therefore clobbering them) you might want to look at other code
sharing methods like mixins since you may not have a true inheritence
hierarchy.

of course most of my inheritence hierarchies aren't technically 'valid' either
:wink:

Just having a builtin simple class-equivalent to the attr methods would be
very useful to me, which I think was the point of the initial post. I love
how Ruby's classes are just normal objects, but the fact that I have to
manually define all of these attr_accessors for the classes themselves gets
pretty annoying.

you have that already

   class C
     class << self
       attr 'foo'
     end
   end

I'll check into 'traits', but I don't think I can use it for this
project, since I have to mostly stick to libs that are part of the
standard library.

it's pure ruby so you can always just cut and paste it. :wink:

cheers.

-a

···

On Tue, 12 Jul 2005, Luke Kanies wrote:

On Tue, 12 Jul 2005, Ara.T.Howard wrote:

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
My religion is very simple. My religion is kindness.
--Tenzin Gyatso

===============================================================================

The @@class_var syntax is unique in that you can assign a value to a class
and it is propogated down.

Yep, I know, and I almost never use this type of variable.

With class instance vars, class << self; attr_accessor :class_var; end
this will only give you a "slot", you still have to populate the slot with
something. So for a subclass to inherit values, it would need to have
something populating the subclasses values each time the class is inherited
presumably in the "inherited" method or manually as in Ara's "init" method.
The same goes for an instance attribute, it needs to be initialized in the
initialize method, presumably, you can't assign defaults with the
attr_accessor method.

Yeah, I know how the variable type behaves; as I said, I'm using tons of
them.

In my case, I've got classes set up that are perfectly functional with
only class instance variables defined, but they can define extra methods
if they want. For instance:

    # an abstract base class
    class Base
        def self.dostuff
            unless defined? @data
                raise "Data must be defined
            end
            ... do stuff ...
        end
    end

    class Sub < Base
        @data = %w{this is data}
    end

    class OtherSub < Base
        @data = %w{this is more data}
    end

I use this basic construct over and over, but I'm using it almost to
death in my current project which is right about 10k lines now.

···

On Tue, 12 Jul 2005, Jeffrey Moss wrote:

--
One of the Ten Commandments for Technicians
        (7) Work thou not on energized equipment, for if thou dost, thy
            fellow workers will surely buy beers for thy widow and
            console her in other ways.
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://config.sage.org

it just ducks into the singleton class of whatever object you use it on. in
the case the object is a class and it just so happens that class methods are
singleton methods of classes so you end up defining class methods this way

Ok.

[...]

using this construct in classes just so happens to work nicely since singleton
methods of classes are also know as 'class methods' for instances of that
class.

Ok, just making sure.

there's no need really - but it allows you to do things like this that cannot
be done otherwise:

   class C
     class << self
       attr 'a'
       attr 'b'
       alias c a
       alias d b
     end
     attr 'a'
     attr 'b'
   end

so now we have instance method 'a' and 'b' and class methods 'a' and 'b' and
aliases for those two class methods 'c' and 'd' respectively. because the
'attr' and 'alias' calls are in class singleton scope here it works.

Yeah, that's what I'll be using, since it should work just fine for my
purposes, but I think it's a touch obfuscated. Of course, I've already
admitted to not fully grokking the 'class << self' syntax, so that
doesn't help.

if they don't it's doubtful that they are real subclasses. most OO theory
would suggest that any subclass (subtype) is a specialzation only of the
base class - eg it should only ADD new behaviour. be definition that means
any existing class vars should be inherited. if you aren't inheriting class
vars (and therefore clobbering them) you might want to look at other code
sharing methods like mixins since you may not have a true inheritence
hierarchy.

I agree, I probably don't have "valid" heirarchies. I would probably
describe most of my heirarchies with a type at the type, and then
instances of that type below it, and then instances of those instances
below that. For instance (similar to the other example I just sent):

    class Type
        class << self
            attr_accessor :params
        end

        # class method
        def self.each
            unless defined? @params
                raise "@params not defined for %s" % self
            end
            @params.each { |param| yield param }
        end

        def =(param,value)
            @params[param] = value
        end

        def (param)
            @params[param]
        end

        # instance method; notice this is a hash, not an array
        def each
            unless defined? @params
                raise "@params not defined for %s" % self
            end
            @params.each { |param,value| yield param, value }
        end

        def initialize(hash)
            @params = {}
            self.class.each { |param|
                if hash.include?(param)
                    self[param] = value
                    hash.delete(param)
                else
                    raise "%s requires parameter %s" %
                        [self.class, param]
                end
            }

            if hash.length > 0
                raise "Unknown parameter(s) '%s'" % hash.keys.join(" ")
            end
        end
    end

    class Sub < Base
        @params = [:name, :address]
    end

    instance = Sub.new(
        :name => "Luke",
        :address => "42 Earth"
    )

I really feel like this is a type at the top, with an instance of the
Base class below that, and then an instance of the instance below that.
I expect that I'm being retarded here, and there's some significantly
better way of doing this, but it's working pretty darn well for me, so
I'm sticking with it unless someone else has a better idea.

of course most of my inheritence hierarchies aren't technically 'valid' either
:wink:

Not that I'd know how to tell...

you have that already

   class C
     class << self
       attr 'foo'
     end
   end

Yah, and that's what I'll be using now that I (basically) understand it,
but I still think it's pretty obfuscated.

> I'll check into 'traits', but I don't think I can use it for this
> project, since I have to mostly stick to libs that are part of the
> standard library.

it's pure ruby so you can always just cut and paste it. :wink:

The above is sufficient for now, but we'll see.

Thanks,
Luke

···

On Tue, 12 Jul 2005, Ara.T.Howard wrote:

--
Writing is not necessarily something to be ashamed of, but do it in
private and wash your hands afterwards. --Robert Heinlein
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://config.sage.org

[...]

    class Type

[...]

    end

    class Sub < Base
        @params = [:name, :address]
    end

Oops; obviously, this should have been:

    class Sub < Type
         @params = [:name, :address]
    end

Carry on.

···

On Mon, 11 Jul 2005, Luke Kanies wrote:

--
If you would be a real seeker after truth, it is necessary that at
least once in your life you doubt, as far as possible, all things.
-- Rene Descartes
---------------------------------------------------------------------
Luke Kanies | http://reductivelabs.com | http://config.sage.org

Hi --

Yeah, that's what I'll be using, since it should work just fine for my
purposes, but I think it's a touch obfuscated. Of course, I've already
admitted to not fully grokking the 'class << self' syntax, so that
doesn't help.

It puts you in the scope of an object's singleton class (i.e., the
class where those methods reside which are unique to this object). I
sometimes wonder whether all the "class << self" examples obscure the
fact that this is a general-purpose thing. In case that's the case,
here's an example:

    str = "I am a string"
    class << str
      def x
        puts "method illustrating singleton class"
      end
    end

at which point you can do:

    str.x

In general, "<< obj" is just a way of telling the "class" keyword that
the class you wish to enter has no name, but is the (anonymous)
singleton class of obj. You could in fact do:

   class C
     # stuff
   end

and then later:

   class << C
     attr_reader :whatever
   end

which is another non-"self" example.

David

···

On Tue, 12 Jul 2005, Luke Kanies wrote:

--
David A. Black
dblack@wobblini.net

It always seems clearer to me when written as:

    str = "I am a string"
    def str.x
      puts "method illustrating singleton class"
    end

I understand that the method is really defined in the
anonymous singleton class associated with str but the
'def object.method' syntax is more self-explanatory
(to me) than the 'class <<obj' syntax.

Gary Wright

···

On Jul 11, 2005, at 11:20 PM, David A. Black wrote:

I sometimes wonder whether all the "class << self" examples obscure the
fact that this is a general-purpose thing. In case that's the case,
here's an example:

   str = "I am a string"
   class << str
     def x
       puts "method illustrating singleton class"
     end
   end

Hi --

I sometimes wonder whether all the "class << self" examples obscure the
fact that this is a general-purpose thing. In case that's the case,
here's an example:

   str = "I am a string"
   class << str
     def x
       puts "method illustrating singleton class"
     end
   end

It always seems clearer to me when written as:

  str = "I am a string"
  def str.x
    puts "method illustrating singleton class"
  end

I understand that the method is really defined in the
anonymous singleton class associated with str but the
'def object.method' syntax is more self-explanatory
(to me) than the 'class <<obj' syntax.

"def obj.meth" is definitely the most direct way to add a method to an
object. But it's not a drop-in replacement for opening up the
object's singleton class. Consider:

   class << obj
     attr_accessor :x
   end

which you could do without opening the class but it would be a pain.
Also, there's a difference between the two techniques in the scope of
constants:

   X = 1
   obj = Object.new

   class << obj
     X = 2
     def b
       X
     end
   end

   def obj.a
     X
   end

   p obj.a # 1
   p obj.b # 2

(Thanks to Guy Decoux for pointing that out a couple of years ago.)

So it can be important to have the "class interface" to the object's
singleton operations.

David

···

On Tue, 12 Jul 2005 gwtmp01@mac.com wrote:

On Jul 11, 2005, at 11:20 PM, David A. Black wrote:

--
David A. Black
dblack@wobblini.net