1
class A
  def self.a
    puts "self: #{self}; superclass: #{superclass}"
  end
end

class B < A
  class << self; undef_method(:a); end  # I'm not allowed to use B.a
  def self.b
    # here I want to call A.a with B as self.
  end
end  

A.a  #=> self: A; superclass: Object
B.b  #=> self: B; superclass: A (expected)

I don't want an alias_method solution. I'm looking for something like this.

UPDATE

The solution doesn't need to be any similar to the link above; it's only a suggestion. For example, I tried to do:

class B < A
  def self.b
    instance_eval(&A.method(:a).to_proc)
  end
end

but this way I get an weird ArgumentError on Ruby 1.8.7.

Community
  • 1
  • 1
Sony Santos
  • 5,435
  • 30
  • 41

3 Answers3

2

I don't think it's doable using the SuperProxy approach you linked to.

In this case, A.method(:a) is a singleton method. Singleton methods can only be bound to the object it was created with. In particular, it cannot be rebound to B.

Here's the first non-working approach I tried:

class B < A
  def self.b
    A.method(:a).unbind.bind(self).call
  end
end

Second non-working approach:

class B < A
  class << self
    define_method :b, A.method(:a)
  end
end

Both generate a "TypeError: singleton method bound for a different object" exception.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Thank for your tries. I've tried the first one, too. I even tried: `instance_eval(&A.method(:a).to_proc)` (inside `def self.b`), but then I get an weird ArgumentError in Ruby 1.8.7. – Sony Santos Apr 25 '11 at 04:58
2

When calling a method in the derived class B, with respect to instances of the derived class there is absolutely no difference between the A instance object and the B instance object. They are exactly the same object.

So when considering instance methods, there is only one single object. It's conceptually possible if slightly tricky, as you noted, to call a method defined in the parent class but with, of course, the derived class as the self instance. There is no way to distinguish between an "A" object and a "B" object, there is but a single instance and they are the "same" for A and B. But for class methods, the parallel with the rebound instance method you referred to simply does not exist.

Now, you are talking about class methods. For class methods, as you know, self is the class. Instances are meaningless. You cannot call class method A.whatever without having class A or its metaclass be self.

In other words, the reason your referenced trick works is because there is only one object, and for a derived instance it's named from the derived class. There is no way to do the opposite without creating a second instance of the underived parent class. But now that we are calling class methods they are .. well .. class methods, so there is no hope of referring to a derived class. How, exactly, could what you want even be defined?

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329
1

Only solution here is to use B.a.

class B < A
  def self.b
    a #=> self: B; superclass: A
  end
end  
Sony Santos
  • 5,435
  • 30
  • 41