Полиморфизм состоит из слов греческого корня: polys (много) и morphe. (форма или форма), и это означает качество или состояние существования в различных формах или их принятия. В программировании это относится к возможности использовать одни и те же методы, но по-разному для разных объектов. Полиморфизм позволяет создавать более динамичные приложения.

Существует несколько способов использования полиморфизма:

Наследование:это одна из особенностей Ообъектно-ориентированного Оориентированного программирования(ООП). Полиморфизм дает нам возможность использовать один и тот же метод для разных объектов.

Чтобы достичь этого полиморфизма, вы должны создать подклассы из каждого отдельного вида животных. Каждый подкласс наследовал бы от суперкласса общий интерфейс. Благодаря наследованию подклассы теперь имеют общие методы из своего суперкласса. Делая это, он обеспечивает гибкость методов вашего суперкласса с точки зрения возможности повторного использования. Затем ваши подклассы зарезервированы для более подробного поведения и выходных данных.

class Animal
  
 def initialize(breed)
   @breed = breed
 end
  
 def make_some_noise
   puts ""
 end
end
class Cat < Animal
  def make_some_noise
    puts "Mew mew"
  end
end
class Dog < Animal
  def make_some_noise
    puts "Woof woof"
  end
end
class Duck < Animal 
  def make_some_noise
    puts "Quackity quack"
  end
end
dog = Dog.new(dog)
dog.make_some_noise # => Woof woof
duck = Duck.new(duck)
duck.make_some_noise # => Quackity quack

Хотя все наши животные относятся к разным типам: кошка, собака и утка, все они ведут себя одинаково — каждое из них может издавать звуки. Каждый тип просто возвращает другой результат. Здесь в дело вступает полиморфизм. Обратите внимание, что вы можете вызвать один и тот же метод для другого объекта, но он вернет другой результат. Метод make_some_noise внутри подклассов переопределяет метод суперкласса и выдает собственные настраиваемые выходные данные подклассов — полиморфизм позволяет этому методу быть более динамичным.

Вы также можете использовать модуль в этом случае, потому что классы имеют общее поведение. С модулем вы не можете создать объект. Модуль должен быть добавлен через «include» в класс. Включение позволяет классу и его объектам иметь одно и то же поведение, объявленное в модуле.

Duck Typing:
Помните, как удобен Ruby и что он динамичен… поэтому Ruby достаточно удобен тем, что вам не нужна иерархия классов объектов с общим интерфейсом, который был бы определенные супер и подклассы или наследование для зависимости кода. С помощью утиной печати вы можете еще больше абстрагироваться и разделить классы. В свою очередь, это делает ваше приложение еще более динамичным, поскольку уменьшает количество зависимостей кода и обеспечивает гибкость. Концепция утиной печати взята из следующей фразы:

Если он ходит, как утка, плавает, как утка, и крякает, как утка, Ruby достаточно счастлив, чтобы относиться к нему как к утке. Ruby не будет тратить время на размышления о том, действительно ли объект является уткой. При утиной типизации объект определяется возможностями — что он может делать, а не типом — что он из себя представляет. Методы внутри класса являются основной проблемой, и если их можно вызвать или нет, то не сам класс. Таким образом, даже если вещь не является настоящей уткой, Ruby будет рассматривать ее как утку.

Утиная типизация относится к тенденции Ruby меньше заботиться о классе объекта и больше заботиться о том, какие методы можно вызывать для него и какие операции можно над ним выполнять».

Вместо того чтобы проверять, относится ли объект к определенному типу, Ruby заботится только о том, может ли объект по-прежнему отвечать на вызов метода. Ruby позволит вам передать любой объект, отвечающий методу другого класса.

class Cat 
  def make_some_noise
    puts "Mew mew"
  end
end
class Dog
  def make_some_noise
    puts "Woof woof"
  end
end
class Duck 
  def make_some_noise
    puts "Quackity quack"
  end
end
class Animal
  def make_some_noise(animal)
    animal.make_some_noise
  end
end
animal = Animal.new
animal.make_some_noise(Cat.new) #=> Meow mew
animal.make_some_noise(Dog.new) #=> Woof woof
animal.make_some_noise(Duck.new)#=> Quackity quack

Таким образом, приведенный выше код все равно будет работать даже с разделенным классом. Метод make_some_noise принимает в качестве переменной животное. Мы можем передать классу Animal любой объект, который отвечает на метод make_some_noise. Один раз мы передаем в метод объекты: Cat, Dog и Duck, даже если объекты из разных классов. Метод просто ведет себя по-разному и выводит по-разному в зависимости от объекта. Однако метод все равно работает — это полиморфизм!

Утиная типизация — это попытка перед покупкой системы тестирования. Если это работает, ура! Если нет, каааа — БУМ… он взорвется вам в лицо. Вы можете прочитать больше о недостатках и преимуществах использования утиной печати в моем следующем посте в блоге…

Если вам нужны дополнительные сведения о утиной типизации g или если вы хотите узнать о полиморфной ассоциации в рельсах.