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

T

Trans

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

Robert Klemme

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"
 
T

Trans

Robert said:
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.
 
R

Robert Klemme

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
 
R

Robert Klemme

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"
 
N

Nobuyoshi Nakada

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
 
T

Trans

Robert said:
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.
 

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

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,818
Latest member
Brigette36

Latest Threads

Top