[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

How to call a class method via the singleton if it exists

Trans

11/18/2006 3:57:00 PM

I want to call a class level method from the the instance level, but I
need it to go through the singeton if it exists. Here is the most basic
example:

class X
def self.f ; "A" ; end
def g ; self.class.f ; end
end

x = X.new
x.g #=> "A"

def x.f; "B"; end
x.g #=> "A"

How do I get the last to return "B"? I know I could use
'(class<<self;self;end)' instead of 'self.class', but that will create
a singelton even if doesn't exist, which seems very wasteful. Yet I
don't recall any (non-hack) way to detect if a singleton is defined. Is
there?

It would be nice if there was a reference with which we could call up
through the class level like this.

T.

6 Answers

Robert Klemme

11/18/2006 4:27:00 PM

0

On 18.11.2006 16:56, Trans wrote:
> I want to call a class level method from the the instance level, but I
> need it to go through the singeton if it exists. Here is the most basic
> example:
>
> class X
> def self.f ; "A" ; end
> def g ; self.class.f ; end
> end
>
> x = X.new
> x.g #=> "A"
>
> def x.f; "B"; end
> x.g #=> "A"
>
> How do I get the last to return "B"? I know I could use
> '(class<<self;self;end)' instead of 'self.class', but that will create
> a singelton even if doesn't exist, which seems very wasteful. Yet I
> don't recall any (non-hack) way to detect if a singleton is defined. Is
> there?
>
> It would be nice if there was a reference with which we could call up
> through the class level like this.

Two ideas attached.

robert

#!/usr/bin/ruby

class Object
# option 1
def dispatch(m,*a,&b)
(respond_to?(m) ? self : self.class).
send(m,*a,&b)
end

# option 2
class Dispatcher
def initialize(*a) @a=a end
def method_missing(m,*a,&b)
@a.each {|o| return o.send(m,*a,&b) if o.respond_to? m}
super
end
end

def disp; Dispatcher.new(self, self.class) end
end

class X
def self.f ; "A" ; end
def g ; self.class.f ; end
def h ; dispatch :f ; end
def i ; disp.f ; end
end

x = X.new
p x.g #=> "A"
p x.h #=> "A"
p x.i #=> "A"

def x.f; "B"; end
p x.g #=> "A"
p x.h #=> "B"
p x.i #=> "B"


Trans

11/18/2006 5:00:00 PM

0


Robert Klemme wrote:
> On 18.11.2006 16:56, Trans wrote:
> > I want to call a class level method from the the instance level, but I
> > need it to go through the singeton if it exists. Here is the most basic
> > example:
> >
> > class X
> > def self.f ; "A" ; end
> > def g ; self.class.f ; end
> > end
> >
> > x = X.new
> > x.g #=> "A"
> >
> > def x.f; "B"; end
> > x.g #=> "A"
> >
> > How do I get the last to return "B"? I know I could use
> > '(class<<self;self;end)' instead of 'self.class', but that will create
> > a singelton even if doesn't exist, which seems very wasteful. Yet I
> > don't recall any (non-hack) way to detect if a singleton is defined. Is
> > there?
> >
> > It would be nice if there was a reference with which we could call up
> > through the class level like this.
>
> Two ideas attached.
>
> robert

thanks robert. you helped clarify that unfortunately I've i mis-stated
the problem, there's a contradiction in my example, what I actually
meant was:

class X
def self.f ; "A" ; end
def g ; self.class.f ; end
end

x = X.new
x.g #=> "A"

# this should be:
class << x
def self.f; "B"; end
end

x.g #=> "A" # want "B"

so #respond_to? won't help b/c I didn't intend #f to be instance level
method. sorry. what i'm asking for, should make a whole lot more sense
now (i hope)

thanks,
T.

Robert Klemme

11/18/2006 5:16:00 PM

0

On 18.11.2006 18:00, Trans wrote:
> Robert Klemme wrote:
>> On 18.11.2006 16:56, Trans wrote:
>>> I want to call a class level method from the the instance level, but I
>>> need it to go through the singeton if it exists. Here is the most basic
>>> example:
>>>
>>> class X
>>> def self.f ; "A" ; end
>>> def g ; self.class.f ; end
>>> end
>>>
>>> x = X.new
>>> x.g #=> "A"
>>>
>>> def x.f; "B"; end
>>> x.g #=> "A"
>>>
>>> How do I get the last to return "B"? I know I could use
>>> '(class<<self;self;end)' instead of 'self.class', but that will create
>>> a singelton even if doesn't exist, which seems very wasteful. Yet I
>>> don't recall any (non-hack) way to detect if a singleton is defined. Is
>>> there?
>>>
>>> It would be nice if there was a reference with which we could call up
>>> through the class level like this.
>> Two ideas attached.
>>
>> robert
>
> thanks robert. you helped clarify that unfortunately I've i mis-stated
> the problem, there's a contradiction in my example, what I actually
> meant was:
>
> class X
> def self.f ; "A" ; end
> def g ; self.class.f ; end
> end
>
> x = X.new
> x.g #=> "A"
>
> # this should be:
> class << x
> def self.f; "B"; end
> end
>
> x.g #=> "A" # want "B"
>
> so #respond_to? won't help b/c I didn't intend #f to be instance level
> method. sorry. what i'm asking for, should make a whole lot more sense
> now (i hope)
>
> thanks,
> T.


Just replace self.class with class<<self;self;end in my code.

robert

Robert Klemme

11/18/2006 9:07:00 PM

0

On 18.11.2006 18:16, Robert Klemme wrote:
>> thanks robert. you helped clarify that unfortunately I've i mis-stated
>> the problem, there's a contradiction in my example, what I actually
>> meant was:
>>
>> class X
>> def self.f ; "A" ; end
>> def g ; self.class.f ; end
>> end
>>
>> x = X.new
>> x.g #=> "A"
>>
>> # this should be:
>> class << x
>> def self.f; "B"; end
>> end
>>
>> x.g #=> "A" # want "B"
>>
>> so #respond_to? won't help b/c I didn't intend #f to be instance level
>> method. sorry. what i'm asking for, should make a whole lot more sense
>> now (i hope)
>>
>> thanks,
>> T.
>
>
> Just replace self.class with class<<self;self;end in my code.
>
> robert
>
How about this?

robert

#!/usr/bin/ruby

class Object
# option 1
def dispatch(m,*a,&b)
[class <<self; self; end, self.class].find {|x| x.respond_to? m}.
send(m,*a,&b)
end

# option 2
class Dispatcher
def initialize(*a) @a=a end
def method_missing(m,*a,&b)
@a.each {|o| return o.send(m,*a,&b) if o.respond_to? m}
super
end
end

def disp; Dispatcher.new(class <<self; self; end, self.class) end
end

class X
def self.f ; "A" ; end
def g ; self.class.f ; end
def h ; dispatch :f ; end
def i ; disp.f ; end
end

x = X.new
p x.g #=> "A"
p x.h #=> "A"
p x.i #=> "A"

class << x
def self.f; "B"; end
end

p x.g #=> "A"
p x.h #=> "B"
p x.i #=> "B"


Nobuyoshi Nakada

11/18/2006 11:09:00 PM

0

Hi,

At Sun, 19 Nov 2006 01:00:15 +0900,
Trans wrote in [ruby-talk:225642]:
> I want to call a class level method from the the instance level, but I
> need it to go through the singeton if it exists. Here is the most basic
> example:

If I were you:

> class X
> def self.f ; "A" ; end
def f; self.class.f; end
def g ; f ; end
> end

--
Nobu Nakada

Trans

11/19/2006 6:13:00 AM

0


Robert Klemme wrote:

> class Object
> # option 1
> def dispatch(m,*a,&b)
> [class <<self; self; end, self.class].find {|x| x.respond_to? m}.
> send(m,*a,&b)
> end

Nice. Looks like that'll work!

Thanks!

T.