thisguy123 thisguy123 - 2 months ago 7
Ruby Question

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.

Answer

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.