[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Singleton Class Constants

jdance

10/11/2006 6:50:00 PM

David Black wrote in Ruby For Rails (page 341):

> (There's also a subtle difference between these two approaches to
> defining a singleton method, involving the scope of constants, but that's an
> arcane point. For the most part, you can treat them as equivalent.)

The subject of singleton methods and constants has recently gotten me
into trouble. Here is a simplified example:

module ExtendMeFirst
BAR = 3
end

module ExtendMeSecond
def print_bar
puts BAR
end
end

class A
extend ExtendMeFirst
extend ExtendMeSecond
end

A.print_bar #=> NameError: uninitialized constant ExtendMeSecond::BAR

Now, I somewhat understand why this doesn't work - the constants are in
different scopes. The challenge is to get around this problem and use
the constant BAR from ExtendMeFirst in module ExtendMeSecond. We
discovered that what we needed to was access the singleton class's
constants, but there is basically no easy way to do this, since there
is no "singleton_class" method in Object/Kernel (which has been
discussed a long time ago on this list). We eventually added one:

class Object
def singleton_class
class << self; self; end
end
end

And then doing this allowed us to get to the constant:

module ExtendMeSecond
def print_bar
puts singleton_class::BAR
end
end

Is there a better way to do this? What is the "arcane point" about
singleton methods and constants?

11 Answers

Ara.T.Howard

10/11/2006 7:04:00 PM

0

dblack

10/11/2006 7:06:00 PM

0

dblack

10/11/2006 7:14:00 PM

0

Sean

10/11/2006 7:18:00 PM

0

> > Is there a better way to do this?I don't think there's any way that doesn't involve some kind of
> coupling, since you're basically printing one module's constant from
> another module (using "module" as class-or-module). The way you've
> done it presupposes that ExtendMeSecond will indeed be mixed in to a
> singleton class subsequent to the mixing in of ExtendMeFirst. You
> could, instead, cut out one leg of the journey and just say:
>
> def print_bar
> puts ExtendMeFirst::BAR
> end
>
> which is a different kind of coupling, but really isn't inherently
> worse than calling Math::PI or any other constant from another module.
>
> David

This problem originally arose from trying to extend/alter some
functionality of Rails in a plugin, and needing access to some
constants defined in a ClassMethods module that uses the:

def self.append_features(base) # :nodoc:
super
base.extend ClassMethods
...

idiom that is used frequently in rails. To me, the "mixin" concept
creates some weird decisions to make with repsect to coupling. In some
other OOP languages, extending the functionality might be done by
creating a new class that derives from ActiveRecord, and then
overriding the functions in question to provide new behavior.

In Ruby/Rails however, especially with plugins, it seems to be much
more common to use the include and extend functionality to bring new
functions into an existing class, or override them. When you do this,
you're frequently going to want to make assumptions about your context
in the new mixin since you know where it's going, however, conceptually
a mixin should be somewhat context ignorant, should it not?

Gary Wright

10/11/2006 7:42:00 PM

0


On Oct 11, 2006, at 3:13 PM, dblack@wobblini.net wrote:
> I prefer it without that, since that makes it deviate from the #class
> method, which it's otherwise precisely parallel to. I'd rather that
> singleton_class work like class than that it work like class_eval.
> Otherwise you've got a situation where all classes except singleton
> classes have to call class_eval, and I don't see any grounds for
> granting that privilege.

I agree with David's point about the discrepancy but couldn't that
be also resolved by changing the standard #class method to behave like
Ara's proposed #singleton_class ?

Gary Wright




dblack

10/11/2006 8:25:00 PM

0

Ara.T.Howard

10/11/2006 8:26:00 PM

0

dblack

10/11/2006 8:41:00 PM

0

Ara.T.Howard

10/11/2006 8:41:00 PM

0

dblack

10/12/2006 12:08:00 AM

0