Delegating class methods

A

abc

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!
 
M

Michael Malone

com>
X-Received-From: This message has been automatically forwarded from the ruby-talk mailing list by a gateway at comp.lang.ruby. If it is SPAM, it did not originate at comp.lang.ruby. Please report the original sender, and not us. Thanks! For more details about this gateway, please visit: http://blog.grayproductions.net/categories/the_gateway
X-Mail-Count: 330023
X-Ml-Name: ruby-talk
X-Rubymirror: Yes
X-Ruby-Talk: <[email protected]>
Bytes: 2848
Xref: number1.nntp.dca.giganews.com comp.lang.ruby:323957

class Klass

extend Forwardable

def_delegators :mad:object :method1, :method2, :method3

def initialize
@object = SomeKlass.new
end

end
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!


=======================================================================
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.
=======================================================================
 
L

lasitha

how would you forward calls from class methods to a class atribute?
[...]

I have to delegate a fairly large number of calls to an attribute. [...]

class Klass
extend Forwardable
def_delegators :mad:object :method1, :method2, :method3

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 :mad:hash, :[], :[]=, :size
end
end

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

Solidarity,
lasitha

[1] Generally a good idea anyway, right?
 
A

Albert Schlef

Arcadio said:
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 :eek:ne, :two, :Tthee
end
end

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

Albert Schlef

Albert said:
You can do the following:

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

class << self
attr_accessor :eek:ne, :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
 
R

Ryan Davis

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 :mad:@hash for the delegators line, but I
couldn't get that to work easily.
 
L

Leo

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 :eek:ne, :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.
 
A

abc

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...
 
R

Ryan Davis

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?).
 
R

Robert Dober

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


--
There are some people who begin the Zoo at the beginning, called
WAYIN, and walk as quickly as they can past every cage until they get
to the one called WAYOUT, but the nicest people go straight to the
animal they love the most, and stay there. ~ A.A. Milne (from
Winnie-the-Pooh)
 
R

Robert Dober

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...
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


--
There are some people who begin the Zoo at the beginning, called
WAYIN, and walk as quickly as they can past every cage until they get
to the one called WAYOUT, but the nicest people go straight to the
animal they love the most, and stay there. ~ A.A. Milne (from
Winnie-the-Pooh)
 
L

lasitha

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=E9s 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
 
R

Ryan Davis

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.
 
G

Gary Wright

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=E9s 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
 
R

Rick DeNatale

[Note: parts of this message were removed to make it a legal post.]

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
 
G

Gary Wright

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.
 
L

lasitha

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

I personally like eigenclass variables [...]

I don't think I've ever seen the term 'eigenclass variables' used in
this way. =A0Every object has instance variables. =A0Classes are objects
and so they have instance variables. =A0There 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.
 
R

Robert Dober

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
 

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
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top