How to Do Polymorphism in Ruby

How do you do polymorphism in Ruby?

edit: added more code for your updated question

disclaimer: I haven't used Ruby in a year or so, and don't have it installed on this machine, so the syntax might be entirely wrong. But the concepts are correct.


The exact same way, with classes and overridden methods:

class Animal
def MakeNoise
return ""
end
def Sleep
print self.class.name + " is sleeping.\n"
end
end

class Dog < Animal
def MakeNoise
return "Woof!"
end
end

class Cat < Animal
def MakeNoise
return "Meow!"
end
end

animals = [Dog.new, Cat.new]
animals.each {|a|
print a.MakeNoise + "\n"
a.Sleep
}

how to do polymorphism in Ruby

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"

How to access a variable in Polymorphism with Ruby?

You're running it in wrong way. You should create instances of concrete shapes and then call methods on them:

[8] pry(main)> circle = Circle.new
=> #<Circle:0x0000563ed7328770>
[9] pry(main)> circle.size = 5
=> 5
[10] pry(main)> circle.calculate_area
=> 12.566370614359172

Does polymorphism exist in Ruby?

Yes, Ruby does support polymorphism.

Consider the case of simple class inheritance where an instance of a derived class "is a" instance of both the child and parent classes:

class Parent; end
class Child < Parent; end
o = Child.new
o.is_a?(Child) # => true
o.is_a?(Parent) # => true

Note that this example is also valid for included modules:

a = Array.new
a.is_a?(Array) # => true
a.is_a?(Enumerable) # => true

Of course, Ruby also encourages duck typing, which may be the source of confusion regarding the question of properly supporting polymorphism.

Is it possible to do polymorphism by doing overloading?

If the addition is what you're after, you can do it more simply as:

def add(*numbers)
numbers.inject(&:+)
end

add(1) # => 1
add(1, 3, 5) # => 9

If you're looking for a more general solution to the problem of how to provide behavior dependent on the number of arguments, then you use *args in the signature and then branch based on args.size:

def foo(*args)
case args.size
when 1
# do something
when 2
# do something else
when (3..5)
# do another thing
end
end

Change polymorphic type in ruby

After some more thought, this just wants to be a state_machine, which is nearly like a case or branching ifs. However, we were able to implement a way to handle this without conditionals that feels pretty good:

class Folder
def initialize(name)
@name = name
@state = ClosedFolderState.new(self)
end

attr_reader :name
attr_accessor :state

def pretty_name
"#{@state.icon} #{@name}"
end

def left_click
@state.left_click
end
end

class ClosedFolderState
def initialize(folder)
@folder = folder
end

def icon
'+'
end

def left_click
@folder.state = OpenFolderState.new(@folder)
end
end

class OpenFolderState
def initialize(folder)
@folder = folder
end

def icon
'-'
end

def left_click
@folder.state = ClosedFolderState.new(@folder)
end
end

This may be overkill, but this seems to meet our goal of just seeing if we can move away from conditionals, and here using a decorator seems to work. I am not saying this would be everyone's preferred solution, but I think this answers my question.

Ruby on Rails - Create polymorphic comment through partial

When you pass a record to a form builder rails uses the polymorphic route helpers* to lookup the url for the action attribute.

To route to a nested resource you need to pass the parent and child(ren) in an array:

bootstrap_form_for([@commentable, @comment])
# or
bootstrap_form_for([@comment.commentable, @comment])

This would give the path /images/:image_id/comments for a new record and /images/:image_id/comments/:id if it has been persisted.

Get specific type of polymorphic association

According to APIdock:

:foreign_type

Specify the column used to store the associated object’s type, if this is a polymorphic association. By default this is guessed to be
the name of the association with a “_type” suffix. So a class that
defines a belongs_to :taggable, polymorphic: true association will use
“taggable_type” as the default :foreign_type.

So, you should use foreign_type in the source association to specify what column stores the associated object's type.

I think you want two methods html and pdf, so you can use it when the source is either Html or Pdf. In this case, I think you should create two methods for it, for example:

def html
source if source_type == "Html"
end

def pdf
source if source_type == "Pdf"
end


Related Topics



Leave a reply



Submit