Test Whether a Ruby Class Is a Subclass of Another Class

Test whether a Ruby class is a subclass of another class

Just use the < operator

B < A # => true
A < A # => false

or use the <= operator

B <= A # => true
A <= A # => true

How can I know whether a class is inherited from another one? Some methods like is_a?

You can use the < operator:

B < A will be true, if B is a subclass of A.

Check if subclass is instance of parent

Try:

@template.is_a?(MessengerTemplate)

As noted in the docs:

Returns true if class is the class of obj, or if class is one of the superclasses of obj or modules included in obj.

MessengerTemplate is a superclass of @template, therefore @template.is_a?(MessengerTemplate) => true.

Ruby: How do we identify whether an object o has a class C as its ancestor in the class hierarchy?

Try obj.kind_of?(Klassname):

1.kind_of?(Fixnum) => true
1.kind_of?(Numeric) => true
....
1.kind_of?(Kernel) => true

The kind_of? method has also an identical alternative is_a?.

If you want to check only whether an object is (direct) instance of a class, use obj.instance_of?:

1.instance_of?(Fixnum) => true
1.instance_of?(Numeric) => false
....
1.instance_of?(Kernel) => false

You can also list all ancestors of an object by calling the ancestors method on its class. For instance 1.class.ancestors gives you [Fixnum, Integer, Precision, Numeric, Comparable, Object, PP::ObjectMixin, Kernel].

How do I check if a variable is an instance of a class?

It's almost exactly the same. You can use Object's instance_of? method:

"a".instance_of? String # => true
"a".instance_of? Object # => false

Ruby also has the is_a? and kind_of? methods (these 2 are aliases, and work exactly the same), which returns true is one of the superclasses matches:

"a".is_a? String # => true
"a".is_a? Object # => true

How can I determine if a class A inherits from class B without instantiating an A object in Ruby?

Sure, just compare the two classes:

if Admin < ActiveRecord::Base
# ...
end

It is interesting to note that while Module#< will return true if Admin inherits from AR::Base, it will return false or nil if that's not the case. false means that it is the otherway around, while nil is for unrelated classes (e.g. String < Range returns nil).

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.

Look up all descendants of a class in Ruby

Here is an example:

class Parent
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end

class Child < Parent
end

class GrandChild < Child
end

puts Parent.descendants
puts Child.descendants

puts Parent.descendants gives you:

GrandChild
Child

puts Child.descendants gives you:

GrandChild


Related Topics



Leave a reply



Submit