Forum: Ruby Delegating class methods

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.
7b00965686932462eb7c765b65c580c4?d=identicon&s=25 Arcadio Rubio garcía (abc)
on 2009-03-01 21:35
(Received via mailing list)
Hi all,

how would you forward calls from class methods to a class atribute?
Like in:

class Foo
  @@hash = {}

  def self.size
    @@hash.size
  end
end

I have to delegate a fairly large number of calls to an attribute. I'm
currently using method_missing, but I was wondering if there was a
cleaner way to do that as the method names are known at load time. I
didn't find any using the standard library. Perhaps using some
metaprogramming.

Thanks!
699c00ad35f2755810b4aa5f423d73e2?d=identicon&s=25 Albert Schlef (alby)
on 2009-03-02 07:09
Arcadio Rubio garcía wrote:
> Hi all,
>
> how would you forward calls from class methods to a class atribute?

You can do the following:

  class Foo
    @one = 1
    @two = 2
    @three = 3

    class << self
      attr_accessor :one, :two, :Tthee
    end
  end

(Why are you doing '@@' instead of '@'?)
699c00ad35f2755810b4aa5f423d73e2?d=identicon&s=25 Albert Schlef (alby)
on 2009-03-02 07:12
Albert Schlef wrote:
> You can do the following:
>
>   class Foo
>     @one = 1
>     @two = 2
>     @three = 3
>
>     class << self
>       attr_accessor :one, :two, :Tthee
>     end
>   end
>
> (Why are you doing '@@' instead of '@'?)

BTW, there's some glitch here. Let's say you inherit from Foo:

  class Momo < Foo
  end

  puts Momo.one  # won't print "1" !!!

The assignments to the attirbutes (in Foo's body) are happening in Foo's
bag, not in Momo's bag
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2009-03-02 07:49
(Received via mailing list)
On Mar 1, 2009, at 12:33 , abc wrote:

> how would you forward calls from class methods to a class atribute?

I'm not thrilled that you have to use a class method to access the
attribute, but this works:

> class Foo
>   extend SingleForwardable
>   def self.hash; @@hash ||= {}; end
>   def_delegators :hash, :size, :keys
> end
>
> p Foo.size
> p Foo.keys

It'd be ideal if you could use :@@hash for the delegators line, but I
couldn't get that to work easily.
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2009-03-02 07:50
(Received via mailing list)
On Mar 1, 2009, at 22:08 , Albert Schlef wrote:

> (Why are you doing '@@' instead of '@'?)

Because, the OP wanted to use class vars, not class instance vars.
87ef5d1e14b148eb596433bc17ffe690?d=identicon&s=25 Leo (Guest)
on 2009-03-02 09:20
(Received via mailing list)
> BTW, there's some glitch here. Let's say you inherit from Foo:

I'm not sure this can really be called a glitch because that's simply
the way self.instance-variables (or whatever their correct name is)
work. One solution would be to create a inherited class method that
copies the variables from the super class to the subclass.

    class Foo
        @one = 1
        @two = 2
        @three = 3

        class << self
            attr_accessor :one, :two, :three

            def inherited(sub)
                sub.one = one
                sub.two = two
                sub.three = three
            end
        end
    end

    class Momo < Foo
    end

    Momo.one #=> 1


That's cumbersome of course and it would be great if ruby had a
construct to do this automatically with having to define an inherited
hook.

--
Leo

The end is here -->
7b00965686932462eb7c765b65c580c4?d=identicon&s=25 Arcadio Rubio garcía (abc)
on 2009-03-02 12:07
(Received via mailing list)
I'm the OP. Thank you all for your replies.

Sorry if the question wasn't clear enough. I wanted to register all
the instances of a class, so the original idea was to use a hash class
variable to do that.

Of course there are a number of gotchas if you want to make the code
concise using this approach, so an alternative solution is to declare
another class, make it a Singleton and use it for that purpose.

I'm not a seasoned Ruby programmer, but I think I was totally right in
the idea of using class variables (@@hash). I cannot see why some
people are surprised. I'd be very happy if somebody could shed some
light on the issue, because maybe I'm missing something...
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2009-03-02 12:13
(Received via mailing list)
On Mar 2, 2009, at 03:05 , abc wrote:

> I'm not a seasoned Ruby programmer, but I think I was totally right in
> the idea of using class variables (@@hash).

No, using a class var there was totally appropriate.

In the case of your design, depending on what you're actually trying
to accomplish by registering every instance, you can forgo the
registration hash and use:

   ObjectSpace.each_object(YourClass) { |obj| ... }

That only iterates live objects and also has the disadvantage of not
working in jruby or rubinius (yet?).
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2009-03-02 12:59
(Received via mailing list)
On Mon, Mar 2, 2009 at 7:49 AM, Ryan Davis <ryand-ruby@zenspider.com>
wrote:
>
> On Mar 1, 2009, at 22:08 , Albert Schlef wrote:
>
>> (Why are you doing '@@' instead of '@'?)
>
> Because, the OP wanted to use class vars, not class instance vars.
Yes but we do not allow this (easily) ;)

Seriously OP are you sure you want class variables??
And if you're answer is yes, let me ask you the following question:
Are you sure you want to use class variables??
And if you are not I am happily going further in explaining why ;).

Cheers
Robert
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2009-03-02 13:03
(Received via mailing list)
On Mon, Mar 2, 2009 at 12:05 PM, abc <arcadiorubiogarcia@gmail.com>
wrote:
> I'm not a seasoned Ruby programmer, but I think I was totally right in
> the idea of using class variables (@@hash). I cannot see why some
> people are surprised. I'd be very happy if somebody could shed some
> light on the issue, because maybe I'm missing something...
>
oops sorry, you made your point already.
Well if you use class variables they will be shared by all your
subclasses, if that is what you want, perfect.

Often one does not want that behavior, hence the surprise ;), because
a superclass generally shall not know about its subclasses.
Implications on maintenance and reuse are heavy! But there are cases
where it is fine, just ponder the question carefully :)

Cheers
Robert
770048af205ed307b8cf35ae2282ee2f?d=identicon&s=25 Michael Malone (Guest)
on 2009-03-02 15:02
(Received via mailing list)
class Klass

   extend Forwardable

   def_delegators :@object :method1, :method2, :method3

    def initialize
       @object = SomeKlass.new
    end

end
>   end
>
=======================================================================
This email, including any attachments, is only for the intended
addressee.  It is subject to copyright, is confidential and may be
the subject of legal or other privilege, none of which is waived or
lost by reason of this transmission.
If the receiver is not the intended addressee, please accept our
apologies, notify us by return, delete all copies and perform no
other act on the email.
Unfortunately, we cannot warrant that the email has not been
 altered or corrupted during transmission.
=======================================================================
E16e84e861c1815ce11ba7bd851c857d?d=identicon&s=25 lasitha (Guest)
on 2009-03-02 15:26
(Received via mailing list)
On Mon, Mar 2, 2009 at 4:35 PM, abc <arcadiorubiogarcia@gmail.com>
wrote:
> I'm the OP. Thank you all for your replies.

Hello OP :)

> I'm not a seasoned Ruby programmer, but I think I was totally right in
> the idea of using class variables (@@hash). I cannot see why some
> people are surprised. I'd be very happy if somebody could shed some
> light on the issue, because maybe I'm missing something...

There is a school of thought that eigenclass [1] instance variables
are generally preferred over  @@class_variables.  Folks coming to ruby
from other languages often miss the distinction but you'll find many
exposés on this [2], including in the Pickaxe.

I personally like eigenclass variables - they provide all the
capability of class variables, fit elegantly into ruby's object model
and follow all the rules of instance variables. So i don't ever bother
with class vars.

It's important to note this is completely orthogonal to the discussion
about whether it's appropriate to use any class-level state at all.
That has been adequately addressed in this thread already, but it's
possible some of the questioning about class variables may actually
have revolved around whether to use eigenclass variables instead.

Solidarity,
lasitha.

[1] a.k.a singleton class, metaclass, etc.
[2] http://tinyurl.com/3xeef2
    http://tinyurl.com/2rnzrf
    http://tinyurl.com/2thspb
    http://tinyurl.com/2p3wc6
5a837592409354297424994e8d62f722?d=identicon&s=25 Ryan Davis (Guest)
on 2009-03-02 20:13
(Received via mailing list)
On Mar 2, 2009, at 06:24 , lasitha wrote:

> There is a school of thought that eigenclass [1] instance variables
> are generally preferred over  @@class_variables.

for the record, I'm NOT in this school of thought. I'm in the school,
across the street, lobbing water balloons at this school. I've never
ONCE had a design that needed class instance variables and I use class
variables a fair amount. The non-inheritability of class instance
variables is a deterrent imo.

Since this is a religious argument, I will _not_ debate this topic on
the mailing list, so don't bother arguing the matter.
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2009-03-02 23:06
(Received via mailing list)
On Mar 2, 2009, at 9:24 AM, lasitha wrote:
> There is a school of thought that eigenclass [1] instance variables
> are generally preferred over  @@class_variables.  Folks coming to ruby
> from other languages often miss the distinction but you'll find many
> exposés on this [2], including in the Pickaxe.
>
> I personally like eigenclass variables - they provide all the
> capability of class variables, fit elegantly into ruby's object model
> and follow all the rules of instance variables. So i don't ever bother
> with class vars.

I don't think I've ever seen the term 'eigenclass variables' used in
this way.  Every object has instance variables.  Classes are objects
and so they have instance variables.  There is no need to talk about
eigen classes (or the more common term, singleton classes) when you
are talking about alternatives to class variables.

The main confusion with Ruby class variables comes from:
   -- Ruby class variables have syntax similar to instance variables
      but much different semantics
   -- Ruby class variables are assumed to be analogous to C++ class
      variables (or Java class variables) but that is the wrong
      analogy. Ruby instance variables of class objects is the more
      appropriate comparison.

It would be nice if there was a common term for 'instance variables
of class objects' but 'eigenclass variables' isn't it.

Gary Wright
E16e84e861c1815ce11ba7bd851c857d?d=identicon&s=25 lasitha (Guest)
on 2009-03-02 23:24
(Received via mailing list)
On Mon, Mar 2, 2009 at 2:27 AM, Michael Malone
<michael.malone@tait.co.nz> wrote:
>
>   def initialize
>      @object = SomeKlass.new
>   end
> end

No, that would forward to an instance variable and only work with
Klass instances.

If the OP doesn't mind using a singleton class variable instead of a
class variable [1], then we can still use forwardable:

class Foo
  @hash = {}
  class << self
    extend Forwardable
    def_delegators :@hash, :[], :[]=, :size
  end
end

Foo[:bar] = 'baz'
Foo.size #=> 1

Solidarity,
lasitha

[1] Generally a good idea anyway, right?
8f6f95c4bd64d5f10dfddfdcd03c19d6?d=identicon&s=25 Rick Denatale (rdenatale)
on 2009-03-03 00:05
(Received via mailing list)
On Mon, Mar 2, 2009 at 5:05 PM, Gary Wright <gwtmp01@mac.com> wrote:

>
>
>
> It would be nice if there was a common term for 'instance variables
> of class objects' but 'eigenclass variables' isn't it.
>

I think that the common term is class instance variables, i.e. they are
instance variables of a class object.

This is also what they are called in Smalltalk, which also has class
variables which are implemented as a name scope visible to a class and
its
subclasses, not often used, but when they are it's mostly to define
named
constant values.

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 Gary Wright (Guest)
on 2009-03-03 05:12
(Received via mailing list)
On Mar 2, 2009, at 5:57 PM, Rick DeNatale wrote:

> On Mon, Mar 2, 2009 at 5:05 PM, Gary Wright <gwtmp01@mac.com> wrote:
>> It would be nice if there was a common term for 'instance variables
>> of class objects' but 'eigenclass variables' isn't it.
>>
>
> I think that the common term is class instance variables, i.e. they
> are
> instance variables of a class object.

Sure that works but I also think it is the cause of some confusion
because 'class instance variable' is quite close to 'class variable',
yet (in Ruby) those are two very different things.
E16e84e861c1815ce11ba7bd851c857d?d=identicon&s=25 lasitha (Guest)
on 2009-03-03 05:25
(Received via mailing list)
On Tue, Mar 3, 2009 at 3:35 AM, Gary Wright <gwtmp01@mac.com> wrote:
> this way.  Every object has instance variables.  Classes are objects
> and so they have instance variables.  There is no need to talk about
> eigen classes (or the more common term, singleton classes) when you
> are talking about alternatives to class variables.
>
> [...]
>
> It would be nice if there was a common term for 'instance variables
> of class objects' but 'eigenclass variables' isn't it.
>

Retracted :).  I was attempting to use a phrase that couldn't be
mistaken for 'class variable' because i'd guessed the OP was not aware
of the difference.  Actually i meant to write 'eigenclass instance
variables' which is possibly not as egregious.

In any case, i defer to those who've been rubyists much longer than i
and apologize for the confusion.

Solidarity,
lasitha.
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2009-03-03 12:38
(Received via mailing list)
On Tue, Mar 3, 2009 at 5:10 AM, Gary Wright <gwtmp01@mac.com> wrote:
>
> On Mar 2, 2009, at 5:57 PM, Rick DeNatale wrote:

>
> Sure that works but I also think it is the cause of some confusion
> because 'class instance variable' is quite close to 'class variable',
> yet (in Ruby) those are two very different things.
True, yet I think it is the best name I know so far :).
Rick's right it *exactly* describes what they are. And one could
emphasize the issue by saying "instance variables of the class" if one
wants.
Cheers
Robert
This topic is locked and can not be replied to.