Calling a descendant's method

Hello,

is it possible in Ruby to make a method of a class calling another
method to always call the version of that method from the descendant?
I do not know how to put this more clear, so here is an example:

class A
def f
g # what to put here?
end

def g
  "Haha"
end

end

class B < A
def g
“Hoho”
end
end

B.new.f # i want this to return “Hoho”, but it will return “Haha”

Thanks.

Alexey

This returns “HoHo” for me.

On Thu, Aug 25, 2011 at 12:48 PM, Alexey M. <

No it returns “Hoho”!
Now i am confused…

I think i’ve found an explanation: in fact i used a lambda and called a
class method in the body of the lambda, so probably self was bound to
the current self (the abstract class).
Sorry again for the bad question.

In fact, i’ve got a problem in Rails with an abstract class

class AbstractSmartModel < ActiveRecord::Base
self.abstract_class = true

end

I’ve got an error "Could not find table ‘abstract_smarter_models’ ".
I thought that one of the descendants called a method of
AbstractSmartModel
which called another method that only a non-abstract class could have,
but apparently i was wrong.
I’ll try to debug this, sorry for bad question.

UPDATE: the error is raised by a call to
columns_hash inside of a class method of the abstract class.
Do not understand.

Just for the record, my problem was discussed on StackOverflow here:

Alexey M. wrote in post #1018528:

No it returns “Hoho”!
Now i am confused…

ruby checks the B class for f(), and when ruby can’t find f() in B, ruby
moves up the inheritance hierarchy until it finds f() in A:

def f
g()
end

f() executes and inside f() ruby finds the statement:

g()

ruby must call all methods with an object, and if you don’t specify the
object that is calling the method, then ruby uses self. So g() is
equivalent to:

self.g()

What is self? Inside a method, self is equal to the object that called
the method . What object called f()? An instance of B called f(), so
inside f() self=‘the B instance’. That means self.g is equivalent to:

‘the B instance’.g()

So ruby first checks the B class for a method called g(), and if not
found ruby moves up the inheritance chain again.

Alexey M. wrote in post #1018529:

In fact, i’ve got a problem in Rails with an abstract class

class AbstractSmartModel < ActiveRecord::Base
self.abstract_class = true

end

Inside a class, but outside any method definitions, self equals the
class. So the line:

self.abstract_class = true

is equivalent to:

AbstractSmartModel.abstract_class = true

I’ve got an error "Could not find table ‘abstract_smarter_models’ ".

I don’t know what that indicates.

I thought that one of the descendants called a method of
AbstractSmartModel
which called another method that only a non-abstract class could have,
but apparently i was wrong.
I’ll try to debug this, sorry for bad question.

UPDATE: the error is raised by a call to
columns_hash inside of a class method of the abstract class.
Do not understand.

If you have something like this:

class AbstractSmartModel < ActiveRecord::Base
self.abstract_class = true

def AbstractSmartModel.do_stuff
columns_hash(…)
end

end

The you are going to be calling the do_stuff() method like this:

AbstractSmartModel.do_stuff

…which means that inside the do_stuff() method, self is going to be
equal to AbstractSmartModel. From my previous post, you know that the
method call:

columns_hash()

is equivalent to:

self.columns_hash()

and because self=AbstractSmartModel, that line is equivalent to:

AbastractSmartModel.columns_hash()

Alexey M. wrote in post #1018534:

I think i’ve found an explanation: in fact i used a lambda and called a
class method in the body of the lambda, so probably self was bound to
the current self (the abstract class).
Sorry again for the bad question.

class Dog
def self.get_val
10
end

def self.do_stuff
#self = Dog

x = 5
my_lambda = lambda { get_val() + x}  #self.get_val()

x += 1000
return my_lambda

end

end

class Cat
def self.get_val
0
end

def self.execute_lambda(callable)
#self = Cat

x = 0
puts callable.call  #{get_val() + x}.call()

end
end

a_lambda = Dog.do_stuff
Cat.execute_lambda(a_lambda)

–output:–
115

A block ‘closes’ over the variables in the surrounding scope, which
means a block sees the variables at the time the block was created–not
at the time the block is executed. Blocks are written like this:

y = 10
lambda {|x| puts x+y #this is a block}

and like this:

y = 10
some_method.each do |x|
#this is a block
puts x + y
end

self is like a local variable that ruby assigns a value to (the value
depends on where you are in the code).

@7stud thanks for a good example.
(There is a typo: the output is 1015.)

I was confused whether self was a method or a keyword, or a local
variable.
So, apparently it behaves like a local variable.

Also the difference between bounding to a variable and (not) to the
variable’s value is tricky.

And i see that there is an essential difference between lambdas and
methods defined with def, as lambdas are bound to the current scope,
and methods are not.
This makes sense as lambdas are objects, and methods are called on
objects.

Thanks,

Alexey.

P.S. I like this article about lambdas, blocks, etc.:
http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/