John Von Neumann
John Von Neumann

Reputation: 935

Why do we use super in ruby when I can inherit without its use?

I have searched on here for an answer to this question and couldn't find what I was after (in exact terms) so I'm gonna be slightly greedy and ask for some of the communities time. I hope to make my question as applicable as possible.

So, some context, I've been struggling with the idea of classes, class variables and methods for the last week but over the last 2 days have made serious headways in my understanding. However now I am faced with inheritance and can't work out why super would be used when I can just inherit without using it.

For example:

class Animal 
   def initialize (type, breed, age)
     @type = type
     @breed = breed
     @age = age
   end
end

class Dog < Animal
end

class Cat < Animal
end

class Fish 
end

woof = Dog.new("dog", "shitzu", 12)
meow = Cat.new("cat", "tabby", 5)
fish = Fish.new("fish", "gold", 2)

Output:

=> #<Dog:0x00000001447680 @type="dog", @breed="shitzu", @age=12> 
=> #<Cat:0x0000000140c918 @type="cat", @breed="tabby", @age=5> 
ArgumentError: wrong number of arguments (given 3, expected 0)

As you can see, I have been able to inherit from Animal on both my Dog and Cat classes, which I marked for inheritance, but on my Fish I have not been able to, because I didn't inherit.

If someone could explain why we use super, and point out flaws in my understanding, I'd be very grateful, I understand that I may be completely just misunderstanding usage here, but I'd like to just get it clarified. Thanks for your time, appreciate the help.

Upvotes: 1

Views: 1098

Answers (2)

br3nt
br3nt

Reputation: 9586

Excerpted from Inheritance - What is inherited?. The original author was nus. Attribution details can be found on the contributor page. The source is licenced under CC BY-SA 3.0 and may be found in the Documentation archive. Reference topic ID: 625 and example ID: 14883.

Methods are inherited

class A
  def boo; p 'boo' end
end

class B < A; end

b = B.new
b.boo # => 'boo'

Class methods are inherited

class A
  def self.boo; p 'boo' end
end

class B < A; end

p B.boo # => 'boo'

Constants are inherited

class A
  WOO = 1
end

class B < A; end

p B::WOO # => 1

But beware, they can be overridden:

class B
  WOO = WOO + 1
end

p B::WOO # => 2

Instance variables are inherited:

class A
  attr_accessor :ho
  def initialize
    @ho = 'haha'
  end
end

class B < A; end

b = B.new
p b.ho # => 'haha'

Beware, if you override the methods that initialize instance variables without calling super, they will be nil. Continuing from above:

class C < A
  def initialize; end
 end

c = C.new
p c.ho    # => nil

Class instance variables are not inherited:

class A
    @foo = 'foo'
    class << self
        attr_accessor :foo
    end
end

class B < A; end

p B.foo # => nil

# The accessor is inherited, since it is a class method
#
B.foo = 'fob' # possible

Class variables aren't really inherited

They are shared between the base class and all subclasses as 1 variable:

class A
    @@foo = 0
    def initialize
        @@foo  += 1 
        p @@foo
    end
end

class B < A;end

a = A.new # => 1
b = B.new # => 2

So continuing from above:

class C < A
  def initialize
    @@foo = -10
    p @@foo
  end
end

a = C.new # => -10
b = B.new # => -9

Upvotes: 0

gmcnaughton
gmcnaughton

Reputation: 2293

Using super lets a class override a method that it inherits from its parent and customize it.

For instance, in your example, Dog and Cat inherit #initialize from Animal - but what if we wanted some special logic for Dog?

class Dog < Animal
  def initialize(type, breed, age)
    raise "Sorry, dogs don't live that long!" if age > 100

    # Everything looks good - let Animal#initialize run now
    super
  end
end

This lets Dog customize what its initialize method does, but still call through to the original inherited method.

Upvotes: 4

Related Questions