thefonso
thefonso

Reputation: 3390

how to do polymorphism in Ruby

So here is a more java-esq approach (I think)...I have this code in Ruby

class Human
  def move
    p 'Human move: X'
  end
end


class Computer
  def move
    p'Computer move: O'
  end
end

class Player
  def initialize(letter)
    if letter == 'X'
      return Human.new
    else
      return Computer.new
    end
  end
end

bob = Player.new('X')
bob.move

I'm expecting to get back on cli 'Human move: X' I'm getting an error of the following...

undefined method `move' for #<Player:0x007f8d930895a8> (NoMethodError)

Can anybody help this Ruby noob?

-------------------------discussion------------------------

Now I've just figured a way of doing this in a more, I guess, 'classic' Ruby fashion using inheritance and overriding. Now, this just makes no sense to the sub processors in my mind.I mean, if I do it this way...I could have just required the class files in any other class file and instantiated a new object their. It does not feel truly polymorphic the way it does when you do it in Java....here's the code....

class Player
  def move
    return ""
  end
end

class Human < Player
  def move
    return 'Human move: X'
  end
end


class Computer < Player
  def move
    return'Computer move: O'
  end
end



players = [Human.new, Computer.new]
players.each {|player|
  print player.move
}

Upvotes: 1

Views: 3130

Answers (2)

Sergio Tulentsev
Sergio Tulentsev

Reputation: 230286

You almost made it :) In ruby you can't return an arbitrary object from a constructor. Well, you can, but that return value is ignored. Instead use a Factory Method (in OOP speak).

class Human
  def move
    p 'Human move: X'
  end
end


class Computer
  def move
    p 'Computer move: O'
  end
end

class Player
  def self.get_player(letter)
    if letter == 'X'
      return Human.new
    else
      return Computer.new
    end
  end
end

bob = Player.get_player('X')
bob.move
# >> "Human move: X"

Upvotes: 6

Anthony Alberto
Anthony Alberto

Reputation: 10395

You're calling Player.new, so you'll get a Player object back, no matter what you return in the initialize function. If for some reason you don't want to instantiate Human and Computer directly, do something like that :

class Player
  def self.new_player(letter)
    if letter == 'X'
      return Human.new
    else
      return Computer.new
    end
  end
end

bob = Player.new_player('X')
bob.move #Prints your output

Upvotes: 1

Related Questions