# Полиморфизм (Duck typing)

## Полиморфизм

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

```ruby
class Duck
  def voice
    puts "Hi, I'm a Duck"
  end
end
```

```ruby
class  Goose < Duck
  def voice
    puts "Hi, I'm a Goose"
  end
end
```

```ruby

# Мы ожидаем, что в аргументы метода будет передан какой-то объект у которого мы вызовем метод
def animal_voice(animal)
  #  метод voice является общим признаком и для Duck и для Goose
  animal.voice
end

duck = Duck.new
goose = Goose.new

animal_voice(duck) # = Hi, I'm a Duck
animal_voice(goose) # = Hi, I'm a Goose
```

Возможно может показаться, что это сработало благодаря наследованию, но на самом деле наследование здесь никакой роли не играет. И тот и другой класс имеют метод с одинаковым названием `voice`. Метод `animal_voice` не имеет никакой информации какой объект будет ему передан. Мы лишь знаем, что у этого объекта должен быть метод `voice`. Если вы уберете наследование и попробуете запустить код, то **ничего не поменяется**.

## Duck typing

Почему это называют duck typing ? Дословно это переводится как "Утиная типизация", которая гласит: если объект выглядит как утка и может делать тоже самое, что и утка, значит мы можем быть уверены, что это утка. На самом деле с самой уткой тут ничего общего нет, поэтому вместо слово утки можете подставить любое название.

## Итоги

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

И еще раз, полиморфизмом не является то, что мы можем у аргумента метода вызывать метод с одинаковым назывнием. Полиморфизм это возвожность работать с объектами разных классов **по общему признаку**.

## Задание animals

**Внимание ! Это и последующие задания данного модуля с названием `animals` необходимо выполнять в одной и той же директории в корне модуля - `3_oop/animals`**

* перенесите вашу логику перекормления до смерти и замяукивания до смерти в отдельные методы, `def meow_until_death(animal)` и `def eat_until_death(animal)` соответственно, которые будут принимать объект кота в аргументах.
* вызовите эти методы для разных котов
* Создайте несколько экземпляров класса `Dog`. Попробуйте применить ваши методы на объектах класса собаки.
* Убедитесь, что метод работает исправно для собаки и для кота
* Какое поведение вы наблюдаете ?

## Задание company

**Внимание ! Это и последующие задания данного модуля с названием `company` необходимо выполнять в одной и той же директории в корне модуля - `3_oop/company`**

* Создайте класс компании `Company`, содержащей сотрудников и реализующей методы:
  * `hire(employee)` - найм одного сотрудника. В аргументах метод ожидает получить объект на базе класса сотрудника.
  * `hireAll(employes)` - найм списка сотрудников. В аргументах метод ожидает получить массив объектов на базе классов сотрудника.
  * `fire(employee)` - увольнение сотрудника. В аргументах метод ожидает получить объект класса `Employee`
* Создайте классы сотрудников `Manager`, `TopManager` и `Operator` с методом получения информациии о зарплате `get_salary` и условиями начисления зарплаты:
  * `Manager` — зарплата складывается из фиксированной части и бонуса в виде 5% от заработанных для компании денег. Количество заработанных денег для компании генерируйте случайным образом от 115 000 до 140 000 рублей в момент установления заработной платы.
  * `TopManager` — зарплата складывается из фиксированной части и бонуса в виде 150% от заработной платы, если доход компании более 10 млн рублей.
  * `Operator` — зарплата складывается только из фиксированной части.

Рекомендации:

* Чтобы получить данные компании внутри класса сотрудника, настройте хранение ссылки на Company и передавайте объект Company с помощью конструктора.
* Сделайте возможным создание разных экземпляров компании со своим списком сотрудников и доходов.
* Данное задание творческое. Многие ньюансы и подробности были специально опущены, чтобы вы могли сами придумать как та или иная функциональность будет работать.

## Дополнительный материал

* [Полиморфизм](https://blog.appsignal.com/2022/05/25/an-introduction-to-polymorphism-in-ruby-on-rails.html)
* [Duck typing](https://chetan.medium.com/duck-typing-in-ruby-212a25b90cec)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://evgenii-afanasev.gitbook.io/ruby-course/3_oop/4_polymorphism.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
