Reputation: 5545
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.
Upvotes: 1
Views: 2922
Reputation: 5545
Only solution here is to use B.a
.
class B < A
def self.b
a #=> self: B; superclass: A
end
end
Upvotes: 1
Reputation: 146053
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?
Upvotes: 2
Reputation: 223003
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.
Upvotes: 2