Calling Method in Parent Class from Subclass Methods in Ruby

Calling method in parent class from subclass methods in Ruby

If the method is the same name, i.e. you're overriding a method you can simply use super. Otherwise you can use an alias_method or a binding.

class Parent
def method
end
end

class Child < Parent
alias_method :parent_method, :method
def method
super
end

def other_method
parent_method
#OR
Parent.instance_method(:method).bind(self).call
end
end

Calling a subclass method from a superclass

Good question, but you are making it too complicated. Keep in mind a few principles and it should all be clear...

  • The types will be resolved dynamically, so if a show exists anywhere in the object's class hierarchy at the moment it is actually called then Ruby will find it and call it. You are welcome to type in method calls to anything that may or may not exist in the future and it's legal ruby syntax and it will parse. You can type in an expression that includes a reference to this_will_never_be_implemented and no one will care unless it actually gets called.

  • Even in Java, there is only one actual object. Yes, you may have a method in the superclass that's calling a method, but it is an instance of the derived class (as well as an instance of the base class) and so you can count on the new show being called.

  • In a sense, every Ruby class is an abstract class containing stubs for every possible method that might be defined in the future. You can call anything without access qualifiers in the base class or derived class.

If you want a null superclass implementation, you may want to define one that does nothing or raises an exception.

Update: Possibly, I should have just said "call show like any other method" and left it at that, but having come this far I want to add: You can also implement show with Ruby's version of multiple inheritance: include SomeModule. Since you are obviously interested in Ruby's object model, you might implement your attribute with a mixin just for fun.

Can I call a subclass' private method from its parent class?

You're getting it wrong - in your example, there is no such a thing as the parent class calling children methods.

Methods/constants name lookup in Ruby always works "bottom up": first we check if the method is defined in object's class, then in object's class's superclass and so on (this is a huge simplification because Ruby's object model is more complicated, more on this later). So, in your example things happen in roughly the following order:

  1. When you call RoadBike.new runtime checks if there is an initialize methods defined for the class RoadBike. There is no, so we use the implementation defined for its parent class - Bycicle (but the execution context stays the same - it is still RoadBike instance)

  2. When executing Bycicle#initialize runtime encounters another method call - default_chain. At this moment we start method name resolving in the very same manner - starting from the RoadBike context. Does RoadBike have its own implementation of default_chain? Yes, it does, so we simply call it.

The following baby example makes it crystal clear, hopefully:

class Parent
def initialize
puts "Parent Initializer is called"
a
b
end

def a
puts "Parent a is called"
end

def b
puts "Parent b is called"
end
end

class Child < Parent
def b
puts "Child b is called"
end
end

pry(main)> Child.new
Parent Initializer is called
Parent a is called
Child b is called

In reality the methods/constants resolution machinery is more complicated(includes so-called singleton classes). This is a bigger topic that will not fit nicely in SO answer, so I strongly recommend reading "Metaprogramming Ruby 2" by Paolo Perotta where this model is wery well explained in great details from the very practical point of view.

How do I call a super class method

In Ruby 2.2, you can use Method#super_method now

For example:

class B < A
def foo
super + " world"
end

def bar
method(:foo).super_method.call
end
end

Ref: https://bugs.ruby-lang.org/issues/9781#change-48164 and https://www.ruby-forum.com/topic/5356938

Ruby subclass not inheriting parent method or not able to call parent methods in class body

You're calling element as if it was defined as a class method. Any code that is in a class definition but not in a method definition will only be able to call class methods. One way to make the method visible from where your calling it would be to change the signature so it becomes a method of the class object.

class Page
def self.element
end
end

Call subclass method from superclass - Design Pattern

Try this:

class Animals
def self.update
puts "self = #{self} in Animals::update"
if whatever == "Happy Days"
puts "The Fonz rules"
end
end
end

class Tiger < Animals
def self.whatever
"Happy Days"
end
end

Tiger.update
# self = Tiger in Animals::update
# The Fonz rules

Before discussing this, a few notes:

  • I've removed the module Zoo and the instance method Tiger#update as they are not relevant to the question.
  • I've removed self. from self.whatever, as it is not needed (self is assumed if there is no explicit receiver).
  • I've defined the class methods in the more conventional way (but there is nothing wrong with the way the OP defines them).
  • update is only to be invoked from subclasses, as Animal.update would raise a "there's no method or local variable 'whatever'" exception.

The important point here is that Tiger.update invokes the method Animal::update, just as though update had been defined in Tiger, rather than having been inherited from Animal. That's why:

Tiger.methods.include?(:update) #=> true

Therefore, "call a class method of a child class from a parent class" is not correct; Tiger::whatever is being called from the child class. Nothing is being called from the parent class because self never equals Animals when Tiger::update is invoked. This is not just semantics.

Calling a parent instance variable from a sub class in ruby

You are overriding ParentClass#initialize.

Ruby does not magically invoke overridden methods. That would kind of defeat the point of overriding in the first place: for example, often, the reason why you override a method in a subclass, is that the subclass implementation can make use of its knowledge of the subclass to improve performance. It wouldn't make sense for Ruby to invoke the un-optimized version in addition to the optimized one.

However, another big purpose of overriding is differential code reuse: reusing code by only implementing the difference in behavior. In order to do that, Ruby has the super keyword, which allows you to retry the method lookup starting one level up in the ancestors chain.

Here's what that would look like in your case:

class SubClass < ParentClass
def initialize(*)
super
@retries = 0
end
end

This solves the problem with the un-initialized instance variable.

However, there are several other problems with your code. For example, here:

SubClass.new().run()

You are sending the message new to SubClass without any arguments. By default, Class#new is implemented roughly like this:

class Class
def new(...)
obj = allocate
obj.initialize(...)
obj
end
end

[Technically, initialize is private, so we need to break encapsulation here by using something more like obj.__send__(:initialize, ...).]

In other words, new passes its arguments on to initialize. But you have defined ParentClass#initialize with one mandatory keyword parameter profile:, so theoretically, we need to pass an argument to super … but what should we pass? So, instead, we have defined SubClass#initialize to take arguments and pass them on to ParentClass#initialize.

However, you are passing no arguments to SubClass::new here, that we could pass on, and in fact, it isn't clear what arguments we could pass here.

I would like to help you here, but to be honest, the code simply does not make sense, so I don't see how to fix it. Superclasses must never know about their subclasses, in fact, they typically cannot know about their subclasses: many languages allow you to add subclasses after the fact, and Ruby is no exception. Therefore, a superclass knowing about its subclass is a sign that something in your design is very, very, very wrong.

Also note that the very idea of a "parent instance variable" does not make sense: "parent" refers to the class hierarchy, but instance variables belong to instances … that's why they are called "instance" variables, after all.

Ruby on Rails - Call a method for each subclass from the parent class

This happens because rails autoloads classes: Parent doesn't know about its subclasses until they used somewhere or required.

Just require them all manually from the Parent class:

# parent.rb
require 'child1'
require 'child2'

class Parent
def self.parse
self.subclasses.each(&:parse) # how to fix this?
end
end

calling child class method in parent class method

Just use STI here:

class Product < ActiveRecord::Base
self.inheritance_column = :product_type
end

class Orange < Product
end

# then...

> Orange.all
Orange Load (0.1ms) SELECT "products".* FROM "products" WHERE "products"."product_type" IN ('Orange')

Ie. don't do the default_scope or the after_initialize, because Rails already has you covered as soon as you inherit from another model Rails will assume you're using STI and it will add the right thing in the query.

Call derived class instance method from parent class in ruby

Your code already works, so I don't know what the question is.

However, one thing I will say is that there's a standard way to handle control flow like this, without resorting to method meta-programming: yield. You can do something like this:

class Parent
def common_logic(params)
# Some common code which it's Child classes share
yield
end
end

class Child < Parent
def child_method(params)
# ...
end

def some_other_method(params)
common_logic(params) { child_method(params) }
end
end


Related Topics



Leave a reply



Submit