Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby Class Ineritance

I've done a lot of searching about casting an object in Ruby, and can only find examples of casting a string to an integer or vice versa. I'm curious how to cast other, more complex objects..

For Example with these classes...

class Animal
  attr_accessor :weight, :name
end

class Duck < Animal
  def speak
    'Quack'
  end
end

I would expect to be able to do something like the following.

irb> animal = Animal.new
irb> duck = (Duck)animal
irb> duck.speak
=> "Quack"

But I can't quite figure out how to do the casting as I would expect in Java or a similar language.

like image 383
thisguy123 Avatar asked Dec 21 '25 16:12

thisguy123


2 Answers

An object in Ruby is created with a particular class and it will be destroyed with the same class, it never changes. You can't cast, either, all you can do is call functions which convert, a process that involves creating a new object or using another as a proxy.

In your case you can't cast, but you can create a duck with identical properties:

class Animal
  attr_accessor :weight, :name

  def initialize(options)
    # Allow calling new with either an options hash, or another
    # animal that's intended to be cloned.
    case (options)
    when Animal
      @weight = options.weight
      @name = options.name
    when Hash
      @weight = options[:weight]
      @name = options[:name]
    end
  end
end

class Duck < Animal
  def speak(phrase)
    '%s says %s' % [ name, phrase.inspect ]
  end
end

animal = Animal.new(weight: 10, name: 'Bill')

duck = Duck.new(animal)
puts duck.speak('quack!')

A second option is to move the duck-like functionality to a separate module you can mix-in:

module ActsAsDuck
  def speak
    'Quack!'
  end
end

animal.extend(ActsAsDuck)
puts animal.speak

That mixes in any methods in that module into your object instance.

like image 181
tadman Avatar answered Dec 24 '25 08:12

tadman


One thing that you should understand about Ruby is that the concept of type is not related to the class of an object. An object can respond to multiple interfaces other than it's original class (for example, by including modules or defining singleton methods). So, it's not necessary to typecast an object to have access to a particular interface. This means that is not important what an object is, the really important thing its what it's does.

This concept applies to strings and integers too. You don't typecast a string to integer, you ask a string object to create a new integer that is its idea of itself in this form.

If you want a further understanding about this, I suggest you to read about a concept known as Duck typing

In your case you can just instantiate a Duck object directly like this:

irb> duck = Duck.new
irb> duck.quack
=> "Quack"
like image 44
izaban Avatar answered Dec 24 '25 09:12

izaban



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!