Полиморфизм пример ооп: Полиморфизм для начинающих / Хабр

Полиморфизм. Урок 5 курса «Объектно-ориентированное программирование на Python»

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

Например, два разных класса содержат метод total, однако инструкции каждого предусматривают совершенно разные операции. Так в классе T1 – это прибавление 10 к аргументу, в T2 – подсчет длины строки символов. В зависимости от того, к объекту какого класса применяется метод total, выполняются те или иные инструкции.

class T1:
    def __init__(self):
        self.n = 10
 
    def total(self, a):
        return self.n + int(a)
 
 
class T2:
    def __init__(self):
        self.string = 'Hi'
 
    def total(self, a):
        return len(self.string + str(a))
 
 
t1 = T1()
t2 = T2()
 
print(t1.total(35))  # Вывод: 45
print(t2.total(35))  # Вывод: 4

В предыдущем уроке мы уже наблюдали полиморфизм между классами, связанными наследованием. У каждого может быть свой метод __init__() или square() или какой-нибудь другой. Какой именно из методов square() вызывается, и что он делает, зависит от принадлежности объекта к тому или иному классу.

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

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

В Python среди прочего полиморфизм находит отражение в методах перегрузки операторов. Два из них мы уже рассмотрели. Это __init__() и __del__(), которые вызываются при создании объекта и его удалении. Полиморфизм у методов перегрузки операторов проявляется в том, что независимо от типа объекта, его участие в определенной операции, вызывает метод с конкретным именем. В случае __init()__ операцией является создание объекта.

Рассмотрим пример полиморфизма на еще одном методе, который перегружает функцию str(), которую автоматически вызывает функция print().

Если вы создадите объект собственного класса, а потом попробуете вывести его на экран, то получите информацию о классе объекта и его адрес в памяти. Такое поведение функции str() по-умолчанию по отношению к пользовательским классам запрограммировано на самом верхнем уровне иерархии, где-то в суперклассе, от которого неявно наследуются все остальные.

class A:
    def __init__(self, v1, v2):
        self.field1 = v1
        self.field2 = v2
 
 
a = A(3, 4)
b = str(a)
print(a)
print(b)

Вывод:

<__main__.A object at 0x7f251ac2f8d0>
<__main__.A object at 0x7f251ac2f8d0>

Здесь мы используем переменную b, чтобы показать, что функция print() вызывает str() неявным образом, так как вывод значений обоих переменных одинаков.

Если же мы хотим, чтобы, когда объект передается функции print(), выводилась какая-нибудь другая более полезная информация, то в класс надо добавить специальный метод __str__(). Этот метод должен обязательно возвращать строку, которую будет в свою очередь возвращать функция str(), вызываемая функций print():

<a name="__DdeLink__7352_2806398899"></a>class A:
    def __init__(self, v1, v2):
        self.field1 = v1
        self.field2 = v2
 
    def __str__(self):
        return str(self.field1) + " " + str(self.field2)
 
 
a = A(3, 4)
b = str(a)
print(a)
print(b)

Вывод:

Какую именно строку возвращает метод __str__(), дело десятое. Он вполне может строить квадратик из символов:

class Rectangle:
    def __init__(self, width, height, sign):
        self.w = int(width)
        self.h = int(height)
        self.s = str(sign)
    def __str__(self):
        rect = []
        for i in range(self.h): # количество строк
            rect.append(self.s * self.w) # знак повторяется w раз
        rect = '\n'.join(rect) # превращаем список в строку
        return rect
 
b = Rectangle(10, 3, '*')
print(b)

Вывод:

**********
**********
**********

Практическая работа. Метод перегрузки оператора сложения

В качестве практической работы попробуйте самостоятельно перегрузить оператор сложения. Для его перегрузки используется метод __add__(). Он вызывается, когда объекты класса, имеющего данный метод, фигурируют в операции сложения, причем с левой стороны. Это значит, что в выражении

a + b у объекта a должен быть метод __add__(). Объект b может быть чем угодно, но чаще всего он бывает объектом того же класса. Объект b будет автоматически передаваться в метод __add__() в качестве второго аргумента (первый – self).

Отметим, в Python также есть правосторонний метод перегрузки сложения — __radd__().

Согласно полиморфизму ООП, возвращать метод __add__() может что угодно. Может вообще ничего не возвращать, а «молча» вносить изменения в какие-то уже существующие объекты. Допустим, в вашей программе метод перегрузки сложения будет возвращать новый объект того же класса.

Курс с примерами решений практических работ и всеми уроками: android-приложение, pdf-версия.

Что такое полиморфизм в Java • Vertex Academy

Данная статья:


Привет! Это статья об одном из принципов ООП — полиморфизм.

Определение полиморфизма звучит устрашающе 🙂

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

Слово «полиморфизм» может показаться сложным — но это не так. Нужно просто разбить данное определение на части и показать на примерах, что имеется в виду. Поверьте, уже в конце статьи данное определение полиморфизма покажется Вам понятным 🙂

Полиморфизм, если перевести, — это значит «много форм». Например, актер в театре может примерять на себя много ролей — или принимать «много форм».

Так же и наш код — благодаря полиморфизму он становится более гибким, чем в языках программирования, которые не используют принципы ООП.

Так о каких формах идет речь? Давайте сначала приведем примеры и покажем, как на практике проявляется полиморфизм, а потом снова вернемся к его определению.

Как проявляется полиморфизм

Дело в том, что если бы в Java не было принципа полиморфизма, компилятор бы интерпретировал это как ошибку:

Как видите, методы на картинке отличаются значениями, которые они принимают:

  • первый принимает int
  • а второй принимает String

Однако, поскольку в  Java используется принцип полиморфизма, компилятор не будет воспринимать это как ошибку, потому что такие методы будут считаться разными:

Называть методы одинаково — это очень удобно. Например, если у нас есть метод, который ищет корень квадратный из числа, гораздо легче запомнить одно название (например,

sqrt()), чем по одному отдельному названию на этот же метод, написанный для каждого типа:

Как видите, мы не должны придумывать отдельное название для каждого метода — а главное их запоминать! Очень удобно.

Теперь Вы можете понять, почему часто этот принцип описывают фразой:

Один интерфейс — много методов

Это предполагает, что мы можем заполнить одно название (один интерфейс), по которому мы сможем обращаться к нескольким методам.

Перегрузка методов

То, что мы показывали выше — несколько методов с одним названием и разными параметрами — называется перегрузкой. Но это был пример перегрузки метода в одном классе

. Но бывает еще один случай — переопределение методов родительского класса.

Переопределение методов родителя

Когда мы наследуем какой-либо класс, мы наследуем и все его методы. Но если нам хочется изменить какой-либо из методов, который мы наследуем, мы можем всего-навсего переопределить его. Мы не обязаны, например, создавать отдельный метод с похожим названием для наших нужд, а унаследованный метод будет «мертвым грузом» лежать в нашем классе.

Именно то, что мы можем создать в классе-наследнике класс с таким же названием, как и класс, который мы унаследовали от родителя, и называется переопределением.

Пример

Представим, что у нас есть такая структура:

Вверху иерархии классов стоит класс Animal. Его наследуют три класса — Cat, Dog и

Cow.

У класса «Animal» есть метод «голос» (voice). Этот метод выводит на экран сообщение «Голос». Естественно, ни собака, ни кошка не говорят «Голос» 🙂 Они гавкают и мяукают. Соответственно, Вам нужно задать другой метод для классов Cat, Dog и Cow — чтобы кошка мяукала, собака гавкала, а корова говорила «Муу».

Поэтому, в классах-наследниках мы переопределяем метод voice(), чтобы мы в консоли получали «Мяу», «Гав» и «Муу».

  • Обратите внимание: перед методом, который мы переопределяем, пишем «@Override«. Это дает понять компилятору, что мы хотим переопределить метод.

Так что же такое полиморфизм

Тем не менее, полиморфизм — это принцип. Все реальные примеры, которые мы приведодили выше — это только способы реализации полиморфизма.

Давайте снова посмотрим на определение, которое мы давали в начале статьи:

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

Выглядит понятнее, правда? Мы показали, как можно:

  • создавать «одноименные методы» в одном классе («перегрузка методов»)
  • или изменить поведение методов родительского класса («переопределение методов»).

Все это — проявления «повышенной гибкости» объектно-ориентированных языков благодаря полиморфизму.


Надеемся, наша статья была Вам полезна. Записаться на наши курсы по Java можно у нас на сайте.


полиморфизм в ООП на Python

Приветствую всех на еще одном внеочередном занятии по ООП. И здесь я хочу затронуть еще один вопрос, который волнует моих подписчиков: что такое полиморфизм в ООП на Python? Если попытаться ответить в двух словах на этот вопрос, то можно было бы сказать так:

Это возможность работы с совершенно разными объектами языка Python единым образом.

Кажется, не особо стало понятнее? Поэтому давайте, как всегда, постигнем суть этого подхода на конкретном примере.

Вначале я продемонстрирую пример, где мы увидим один недостаток, который как раз исправляется с помощью полиморфизма. Предположим, у нас есть два класса Rectangle и Square:

class Rectangle:
    def __init__(self, w, h):
        self.w = w
        self.h = h
 
    def getPerRect(self):
        return 2*(self.w+self.h)
 
 
class Square:
    def __init__(self, a):
        self.a = a
 
    def getPerSq(self):
        return 4*self.a

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

r1 = Rectangle(1, 2)
r2 = Rectangle(3, 4)
 
print(r1.getPerRect(), r2.getPerRect())
 
s1 = Square(10)
s2 = Square(20)
 
print(s1.getPerSq(), s2.getPerSq())

Все отлично, все работает. Но, теперь предположим, что все эти объекты помещаются в коллекцию:

которую можно легко перебрать с помощью цикла for и где бы мы хотели получить значение периметра для каждой фигуры:

for g in geom:
    print( g.getPerRect() )

Как вы понимаете, когда в цикле очередь дойдет до объекта s1, возникнет ошибка, т.к. в классе Square отсутствует метод getPerRect. Конечно, зная, что в коллекции находятся объекты Rectangle и Square, можно было бы в цикле записать проверку:

for g in geom:
    if isinstance(g, Rectangle):
        print( g.getPerRect() )
    else:
        print(g.getPerSq())

и все заработает. Но у такого кода мало гибкости и, например, при добавлении еще одного класса:

class Triangle:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
 
    def getPerTr(self):
        return self.a + self.b + self.c

Получим снова ошибку:

t1 = Triangle(1,2,3)
t2 = Triangle(4,5,6)
geom = [r1, r2, s1, s2, t1, t2]

Конечно, в цикле for можно дополнительно проверить на соответствие классам Square и Triangle, но красоты и гибкости нашей программе это не придаст. Вот как раз здесь очень хорошо применим подход, который и называется полиморфизмом. Мы договоримся в каждом классе создавать методы с одинаковыми именами, например,

getPerimetr

Тогда в цикле будем просто обращаться к этому методу и получать периметры соответствующих фигур:

for g in geom:
    print( g.getPerimetr() )

То есть, Python «понимает» объект какого класса хранится в коллекции и соответственно из этого класса берет метод getPerimetr. Это и есть полиморфизм в действии, когда к разным объектам происходит обращение по одному и тому же имени метода и на выходе получаем разное поведение этой функции.

Полиморфизм в языках программирования — это… Что такое Полиморфизм в языках программирования?

Полиморфи́зм (в языках программирования) — взаимозаменяемость объектов с одинаковым интерфейсом.

Язык программирования поддерживает полиморфизм, если классы с одинаковой спецификацией могут иметь различную реализацию — например, реализация класса может быть изменена в процессе наследования [1].

Кратко смысл полиморфизма можно выразить фразой: «Один интерфейс, множество реализаций».

Полиморфизм — один из четырёх важнейших механизмов объектно-ориентированного программирования (наряду с абстракцией, инкапсуляцией и наследованием).

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

Примеры

Класс геометрических фигур (эллипс, многоугольник) может иметь методы для геометрических трансформаций (смещение, поворот, масштабирование).

Класс потоков имеет методы для последовательной передачи данных. Потоком может быть информация, вводимая пользователем с терминала, обмен данными по компьютерной сети, файл (если требуется последовательная обработка данных, например, при разборе исходных текстов программ).

В объектно-ориентированных языках

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

Класс-потомок сам может быть родителем. Это позволяет строить сложные схемы наследования — древовидные или сетевидные.

Абстрактные(или чисто виртуальные) методы не имеют реализации вообще(На самом деле некоторые языки, например C++, допускают реализацию абстрактных методов в родительском классе — см. абстрактный деструктор). Они специально предназначены для наследования. Их реализация должна быть определена в классах-потомках.

Класс может наследовать функциональность от нескольких классов. Это называется множественным наследованием. Множественное наследование создаёт известную проблему (в C++), когда класс наследуется от нескольких классов-посредников, которые в свою очередь наследуются от одного класса (так называемая «diamond problem»). Если метод общего предка был переопределён в посредниках, неизвестно, какую реализацию метода должен наследовать общий потомок. Решается эта проблема путём отказа от множественного наследования для классов и разрешением множественного наследования для полностью абстрактных классов (т. е. интерфейсов) (C#, Delphi, виртуальное наследование (C++).

В функциональных языках

Полиморфизм в функциональных языках будет рассмотрен на примере языка ad hoc (на основе классов). Их можно отличить следующим образом.

Параметрический полиморфизм

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

Специальный, ad hoc полиморфизм

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

В Haskell есть деление на классы и экземпляры (instance), которого нет в ООП. Класс только определяет набор и сигнатуры методов, экземпляр только реализует их. Т. о. автоматически отпадает проблема множественного наследования. Классы не наследуют и не переопределяют методы других классов — каждый метод принадлежит только одному классу. Такой подход проще, чем сложная схема взаимоотношений классов в ООП. Некоторый тип данных может принадлежать нескольким классам; класс может требовать, чтобы каждый его тип обязательно принадлежал к другому классу, или даже нескольким; такое же требование может выдвигать экземпляр. Это аналоги множественного наследования. Есть и свойства, не имеющие аналогов в ООП. Например, реализация списков как экземпляра класса сравнимых величин требует, чтобы элементы списка также принадлежали к классу сравнимых величин.

Программистам, переходящим от ООП к ФП, следует знать важное отличие их системы классов. Если в ООП класс «привязан» к объекту, т. е. к данным, то в ФП — к функции. В ФП сведения о принадлежности к классу передаются при вызове функции, а не хранятся в полях объекта. Такой подход, в частности, позволяет решить проблему метода нескольких объектов (в ООП метод вызывается у одного объекта). Пример: метод сложения (чисел, строк) требует двух аргументов, причем одного типа.

Неявная типизация

В некоторых языках программирования (например, в Ruby) применяется так называемая утиная типизация (другие названия: латентная, неявная), которая представляет собой разновидность сигнатурного полиморфизма. Таким образом, например, в языке Python полиморфизм не обязательно связан с наследованием.

Заключение

Система классов в ФП и в ООП устроены по-разному, поэтому к их сравнению следует подходить очень осторожно.

Полиморфизм является довольно обособленным свойством языка программирования. Например, классы в C++ изначально были реализованы как препроцессор для C. Для Haskell же существует алгоритм трансляции программ, использующих полиморфизм классов в программы с исключительно параметрическим полиморфизмом.

Немного о реализации. Несмотря на концептуальные различия систем классов в ФП и ООП, реализуются они примерно одинаково — с помощью таблиц виртуальных методов.

См. также

Wikimedia Foundation. 2010.

Полиморфизм

в ООП Java с примером

  • Home
  • Testing

      • Back
      • Agile Testing
      • BugZilla
      • Cucumber
      • Database Testing
      • JUnit
      • LoadRunner
      • Ручное тестирование
      • Мобильное тестирование
      • Mantis
      • Почтальон
      • QTP
      • Назад
      • Центр качества (ALM)
      • 000
      • Центр качества (ALM)
      • 000 Управление тестированием
      • TestLink
  • SAP

      • Назад
      • ABAP 90 004
      • APO
      • Начинающий
      • Basis
      • BODS
      • BI
      • BPC
      • CO
      • Назад
      • CRM
      • Crystal Reports
      • QM4
      • 9000 HRM
      • Заработная плата
      • Назад
      • PI / PO
      • PP
      • SD
      • SAPUI5
      • Безопасность
      • Менеджер решений
      • Successfactors
      • Учебники SAP

        • Apache
        • AngularJS
        • ASP.Net
        • C
        • C #
        • C ++
        • CodeIgniter
        • СУБД
        • JavaScript
        • Назад
        • Java
        • JSP
        • Kotlin
        • Linux
        • Linux
        • Kotlin
        • Linux
        • js
        • Perl
        • Назад
        • PHP
        • PL / SQL
        • PostgreSQL
        • Python
        • ReactJS
        • Ruby & Rails
        • Scala
        • SQL
        • 000
        • SQL
        • 000
        • SQL
        • 000 0003 SQL 000
        • UML
        • VB.Net
        • VBScript
        • Веб-службы
        • WPF
    • Обязательно учите!

        • Назад
        • Бухгалтерский учет
        • Алгоритмы
        • Android
        • Блокчейн
        • Business Analyst
        • Создание веб-сайта
        • CCNA
        • Облачные вычисления
        • 0003 COBOL
        • 000 Compiler
            9000 Встроенный
          • 000 9000 Compiler
          • Ethical Hacking
          • Учебники по Excel
          • Программирование на Go
          • IoT
          • ITIL
          • Jenkins
          • MIS
          • Сети
          • Операционная система
          • Назад
          • Управление проектами Обзоры
          • Salesforce
          • SEO
          • Разработка программного обеспечения
          • VB A
      • Big Data

          • Назад
          • AWS
          • BigData
          • Cassandra
          • Cognos
          • Хранилище данных
          • 0003
          • HBOps
          • 0003
          • HBOps
          • MicroStrategy
      .

      oop — пример полиморфизма в java

      Переполнение стека
      1. Около
      2. Продукты
      3. Для команд
      1. Переполнение стека Общественные вопросы и ответы
      2. Переполнение стека для команд Где разработчики и технологи делятся частными знаниями с коллегами
      3. Вакансии Программирование и связанные с ним технические возможности карьерного роста
      4. Талант Нанимайте технических специалистов и создавайте свой бренд работодателя
      5. Реклама Обратитесь к разработчикам и технологам со всего мира
      6. О компании
      .

      Полиморфизм в Golang — объектно-ориентированное программирование в Go

      Добро пожаловать в учебник №. 28 в серии учебных пособий по Голангу.

      Полиморфизм в Go достигается с помощью интерфейсов. Как мы уже говорили, интерфейсы могут быть неявно реализованы в Go. Тип реализует интерфейс, если он предоставляет определения для всех методов, объявленных в интерфейсе. Посмотрим, как в Go достигается полиморфизм с помощью интерфейсов.

      Полиморфизм с использованием интерфейса

      Считается, что любой тип, который определяет все методы интерфейса, неявно реализует этот интерфейс.

      Переменная типа interface может содержать любое значение, реализующее интерфейс. Это свойство интерфейсов используется для достижения полиморфизма в Go.

      Давайте разберемся с полиморфизмом в Go с помощью программы, которая рассчитывает чистый доход организации. Для простоты предположим, что эта воображаемая организация имеет доход от двух видов проектов, а именно. фиксированный счет и время и материал . Чистая прибыль организации рассчитывается по сумме доходов от этих проектов.Чтобы не усложнять этот урок, мы предположим, что валюта — доллары, и не будем иметь дело с центами. Он будет представлен с использованием int . (Я рекомендую прочитать https://forum.golangbridge.org/t/what-is-the-proper-golang-equivalent-to-decimal-when-dealing-with-money/413, чтобы узнать, как представлять центы. Благодаря Андреас Матушек в разделе комментариев, чтобы указать на это.)

      Давайте сначала определим интерфейс Доход .

        type Income interface {
          вычислить () int
          source () строка
      }
        

      Интерфейс Income , определенный выше, содержит два метода: calculate (), , который вычисляет и возвращает доход из источника, и source () , который возвращает имя источника.

      Теперь давайте определим структуру для типа проекта FixedBilling .

        type FixedBilling struct {
          projectName строка
          biddedAmount int
      }
        

      У проекта FixedBilling есть два поля: projectName , которое представляет имя проекта, и biddedAmount , которое представляет собой сумму, которую организация предложила для проекта.

      Структура TimeAndMaterial будет представлять проекты типа Time и Material.

        type TimeAndMaterial struct {
          projectName строка
          noOfHours int
          hourlyRate int
      }
        

      Структура TimeAndMaterial имеет три имени полей: projectName , noOfHours и hourlyRate .

      Следующим шагом будет определение методов для этих типов структур, которые вычисляют и возвращают фактический доход и источник дохода.

        func (fb FixedBilling) calculate () int {
          вернуть fb.biddedAmount
      }
      
      func (fb FixedBilling) source () string {
          вернуть fb.projectName
      }
      
      func (tm TimeAndMaterial) calculate () int {
          return tm.noOfHours * tm.hourlyRate
      }
      
      func (tm TimeAndMaterial) source () string {
          вернуть tm.projectName
      }
        

      В случае проектов FixedBilling доход — это как раз сумма, предложенная для проекта. Следовательно, мы возвращаем это из метода calculate () типа FixedBilling .

      В случае проектов TimeAndMaterial , доход является произведением noOfHours и hourlyRate .Это значение возвращается из метода calculate () с типом получателя TimeAndMaterial .

      Возвращаем название проекта в качестве источника дохода из метода source () .

      Поскольку обе структуры FixedBilling и TimeAndMaterial предоставляют определения для методов calculate (), и source () интерфейса Income , обе структуры реализуют интерфейс Income .

      Объявим функцию calculateNetIncome , которая рассчитает и распечатает общий доход.

        func calculateNetIncome (ic [] Income) {
          var netincome int = 0
          для _, доход: = диапазон ic {
              fmt.Printf ("Доход от% s = $% d \ n", доход.source (), доход.calculate ())
              чистый доход + = доход. вычислить ()
          }
          fmt.Printf ("Чистая прибыль организации = $% d", чистый доход)
      }
        

      Приведенная выше функция calculateNetIncome принимает в качестве аргумента фрагмент интерфейсов Income .Он вычисляет общий доход, перебирая срез и вызывая метод calculate () для каждого из его элементов. Он также отображает источник дохода, вызывая метод source () . В зависимости от конкретного типа интерфейса Income будут вызываться разные методы calculate () и source () . Таким образом, мы достигли полиморфизма в функции calculateNetIncome .

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


      Единственная оставшаяся часть программы — это основная функция.

        func main () {
          project1: = FixedBilling {projectName: "Project 1", biddedAmount: 5000}
          project2: = FixedBilling {projectName: "Project 2", biddedAmount: 10000}
          project3: = TimeAndMaterial {projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
          yieldStreams: = [] Доход {проект1, проект2, проект3}
          CalculateNetIncome (доходные потоки)
      }
        

      В основной функции выше мы создали три проекта: два типа FixedBilling и один типа TimeAndMaterial .Затем мы создаем срез типа Income с этими тремя проектами. Поскольку в каждом из этих проектов реализован интерфейс Income , можно добавить все три проекта в срез типа Income . Наконец, мы вызываем функцию calculateNetIncome с этим срезом, и она отображает различные источники дохода и доход от них.

      Вот полная программа для справки.

        пакет основной
      
      импорт (
          "fmt"
      )
      
      type Income interface {
          вычислить () int
          source () строка
      }
      
      type FixedBilling struct {
          projectName строка
          biddedAmount int
      }
      
      type TimeAndMaterial struct {
          projectName строка
          noOfHours int
          hourlyRate int
      }
      
      func (fb FixedBilling) calculate () int {
          вернуть fb.biddedAmount
      }
      
      func (fb FixedBilling) source () string {
          вернуть fb.projectName
      }
      
      func (tm TimeAndMaterial) calculate () int {
          return tm.noOfHours * tm.hourlyRate
      }
      
      func (tm TimeAndMaterial) source () string {
          вернуть tm.projectName
      }
      
      func calculateNetIncome (ic [] Income) {
          var netincome int = 0
          для _, доход: = диапазон ic {
              fmt.Printf ("Доход от% s = $% d \ n", доход.source (), доход.calculate ())
              чистый доход + = доход. вычислить ()
          }
          fmt.Printf ("Чистая прибыль организации = $% d", чистый доход)
      }
      
      func main () {
          project1: = FixedBilling {projectName: "Project 1", biddedAmount: 5000}
          project2: = FixedBilling {projectName: "Project 2", biddedAmount: 10000}
          project3: = TimeAndMaterial {projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
          yieldStreams: = [] Доход {проект1, проект2, проект3}
          CalculateNetIncome (доходные потоки)
      }
        

      Бег на детской площадке

      Эта программа выведет

        Доход от проекта 1 = 5000 долларов США
      Доход от проекта 2 = 10000 $
      Доход от проекта 3 = 4000 $
      Чистая прибыль организации = 19000 $
        

      Добавление нового источника дохода к указанной выше программе

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

      Давайте сначала определим тип Advertising и методы calculate (), и source () для типа Advertising .

        тип Рекламная структура {
          adName строка
          CPC int
          noOfClicks int
      }
      
      func (a Advertising) calculate () int {
          вернуть.Цена за клик * a.noOfClicks
      }
      
      func (a Advertising) source () string {
          вернуть a.adName
      }
        

      Тип Advertising имеет три поля: adName , CPC (цена за клик) и noOfClicks (количество кликов). Общий доход от рекламы — это произведение CPC и noOfClicks .

      Давайте немного изменим функцию main , чтобы включить этот новый поток доходов.

        func main () {
          project1: = FixedBilling {projectName: "Project 1", biddedAmount: 5000}
          project2: = FixedBilling {projectName: "Project 2", biddedAmount: 10000}
          project3: = TimeAndMaterial {projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
          bannerAd: = Реклама {adName: "Banner Ad", CPC: 2, noOfClicks: 500}
          popupAd: = Реклама {adName: "Popup Ad", CPC: 5, noOfClicks: 750}
          yieldStreams: = [] Доход {project1, project2, project3, bannerAd, popupAd}
          CalculateNetIncome (доходные потоки)
      }
        

      Мы создали два объявления, а именно: bannerAd и popupAd .Срез yieldStreams включает два только что созданных объявления.

      Вот полная программа после добавления рекламы.

        пакет основной
      
      импорт (
          "fmt"
      )
      
      type Income interface {
          вычислить () int
          source () строка
      }
      
      type FixedBilling struct {
          projectName строка
          biddedAmount int
      }
      
      type TimeAndMaterial struct {
          projectName строка
          noOfHours int
          hourlyRate int
      }
      
      type Advertising struct {
          adName строка
          CPC int
          noOfClicks int
      }
      
      func (fb FixedBilling) calculate () int {
          вернуть fb.biddedAmount
      }
      
      func (fb FixedBilling) source () string {
          вернуть fb.projectName
      }
      
      func (tm TimeAndMaterial) calculate () int {
          return tm.noOfHours * tm.hourlyRate
      }
      
      func (tm TimeAndMaterial) source () string {
          вернуть tm.projectName
      }
      
      func (a Advertising) calculate () int {
          вернуть a.CPC * a.noOfClicks
      }
      
      func (a Advertising) source () string {
          вернуть a.adName
      }
      func calculateNetIncome (ic [] Income) {
          var netincome int = 0
          для _, доход: = диапазон ic {
              fmt.Printf ("Доход от% s = $% d \ n", доход.source (), доход.calculate ())
              чистый доход + = доход. вычислить ()
          }
          fmt.Printf ("Чистая прибыль организации = $% d", чистый доход)
      }
      
      func main () {
          project1: = FixedBilling {projectName: "Project 1", biddedAmount: 5000}
          project2: = FixedBilling {projectName: "Project 2", biddedAmount: 10000}
          project3: = TimeAndMaterial {projectName: "Project 3", noOfHours: 160, hourlyRate: 25}
          bannerAd: = Реклама {adName: "Banner Ad", CPC: 2, noOfClicks: 500}
          popupAd: = Реклама {adName: "Popup Ad", CPC: 5, noOfClicks: 750}
          yieldStreams: = [] Доход {project1, project2, project3, bannerAd, popupAd}
          CalculateNetIncome (доходные потоки)
      }
        

      Бег на детской площадке

      Вышеупомянутая программа выведет

        Доход от проекта 1 = 5000 долларов США
      Доход от проекта 2 = 10000 $
      Доход от проекта 3 = 4000 $
      Доход от баннерной рекламы = 1000 долларов США.
      Доход от всплывающей рекламы = 3750 долларов США.
      Чистая прибыль организации = 23750 $
        

      Вы могли заметить, что мы не внесли никаких изменений в функцию calculateNetIncome , хотя добавили новый поток доходов.Просто это сработало из-за полиморфизма. Поскольку новый тип Advertising также реализовал интерфейс Income , мы смогли добавить его в срез yieldStreams . Функция calculateNetIncome также работала без каких-либо изменений, поскольку она могла вызывать методы calculate () и source () типа Advertising .

      На этом мы подошли к концу этого урока. Хорошего дня.

      Следующее руководство — Defer



      .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *