Я пытаюсь понять, как полиморфизм используется в реальном проекте, но я могу найти только классический пример (или что-то похожее на него) наличия Animal
родительского класса с методом speak()
и многих дочерних классов, которые переопределяют этот метод, и теперь Вы можете вызвать метод speak()
для любого из дочерних объектов, например:
Animal animal;
animal = dog;
animal.speak();
animal = cat;
animal.speak();
object-oriented
data-structures
polymorphism
Кристофер
источник
источник
if(x is SomeType) DoSomething()
часто пишете , возможно, стоит использовать полиморфизм. Для меня полиморфизм - это решение, похожее на то, когда нужно создавать отдельный метод, если я обнаружил, что я повторял код несколько раз, я обычно реорганизую его в метод, и если я обнаружил, что либо делаюif object is this type do this
код часто, то это может быть Стоит рефакторинг и добавление интерфейса или класса.Ответы:
Поток является отличным примером полиморфизма.
Поток представляет собой «последовательность байтов, которые могут быть прочитаны или записаны». Но эта последовательность может исходить из файла, памяти или многих видов сетевых подключений. Или он может служить в качестве декоратора, который упаковывает существующий поток и каким-то образом преобразует байты, например, шифрование или сжатие.
Таким образом, клиенту, использующему Stream, не нужно заботиться о том, откуда поступают байты. Просто их можно читать по порядку.
Кто-то скажет, что
Stream
это неправильный пример полиморфизма, поскольку он определяет множество «функций», которые его разработчики не поддерживают, например, сетевой поток, позволяющий только чтение или запись, но не оба одновременно. Или отсутствие поиска. Но это только вопрос сложности, посколькуStream
его можно подразделить на множество частей, которые могут быть реализованы независимо.источник
Stream
- мой самый любимый пример полиморфизма. Я даже больше не пытаюсь учить людей порочной модели «животное, млекопитающее, собака»,Stream
но они делают лучше.Типичным примером, связанным с играми, может быть базовый класс
Entity
, содержащий общих членов, таких какdraw()
илиupdate()
.Для более чистого примера, ориентированного на данные, может быть базовый класс,
Serializable
обеспечивающий общееsaveToStream()
иloadFromStream()
.источник
Существуют различные виды полиморфизма, один из которых обычно представляет собой полиморфизм во время выполнения / динамическая диспетчеризация.
Высокоуровневое описание полиморфизма времени выполнения состоит в том, что вызов метода выполняет разные вещи в зависимости от типа времени выполнения его аргументов: сам объект отвечает за разрешение вызова метода. Это обеспечивает огромную гибкость.
Один из наиболее распространенных способов использования этой гибкости - это внедрение зависимостей , например, чтобы я мог переключаться между различными реализациями или вводить фиктивные объекты для тестирования. Если я заранее знаю, что будет только ограниченное количество возможных вариантов, я мог бы попытаться жестко закодировать их с помощью условных выражений, например:
Это делает код сложным для подражания. Альтернатива состоит в том, чтобы ввести интерфейс для этой операции foo и написать нормальную реализацию и фиктивную реализацию этого интерфейса, а также «внедрить» требуемую реализацию во время выполнения. «Внедрение зависимости» - сложный термин для «передачи правильного объекта в качестве аргумента».
В качестве примера из реальной жизни я сейчас работаю над некой проблемой машинного обучения. У меня есть алгоритм, который требует модель прогнозирования. Но я хочу попробовать разные алгоритмы машинного обучения. Итак, я определил интерфейс. Что мне нужно от моей модели прогнозирования? Учитывая некоторую входную выборку, прогноз и его ошибки:
Мой алгоритм использует заводскую функцию, которая обучает модель:
Теперь у меня есть различные реализации интерфейса модели, и я могу сравнить их друг с другом. Одна из этих реализаций фактически берет две другие модели и объединяет их в расширенную модель. Так что благодаря этому интерфейсу:
Классический вариант использования полиморфизма в графических интерфейсах. В среде GUI, такой как Java AWT / Swing /…, есть разные компоненты . Интерфейс компонента / базовый класс описывает такие действия, как рисование себя на экране или реагирование на щелчки мыши. Многие компоненты являются контейнерами, которые управляют подкомпонентами. Как такой контейнер может нарисовать себя?
Здесь контейнеру не нужно заранее знать точные типы подкомпонентов - если они соответствуют
Component
интерфейсу, контейнер может просто вызывать полиморфныйpaint()
метод. Это дает мне свободу расширять иерархию классов AWT произвольными новыми компонентами.В процессе разработки программного обеспечения существует много повторяющихся проблем, которые можно решить, применив полиморфизм в качестве метода. Эти повторяющиеся пары «проблема - решение» называются шаблонами проектирования , и некоторые из них собраны в одноименной книге. В терминах этой книги, моя модель машинного обучения для инъекций будет стратегией, которую я использую, чтобы «определить семейство алгоритмов, инкапсулировать каждый и сделать их взаимозаменяемыми». Пример Java-AWT, где компонент может содержать подкомпоненты, является примером композита .
Но не каждый проект должен использовать полиморфизм (помимо включения внедрения зависимостей для модульного тестирования, что является действительно хорошим вариантом использования). Большинство проблем в остальном очень статичны. Как следствие, классы и методы часто используются не для полиморфизма, а просто как удобные пространства имен и для красивого синтаксиса вызова метода. Например, многие разработчики предпочитают вызовы методов,
account.getBalance()
а не эквивалентные вызовы функцийAccount_getBalance(account)
. Это прекрасный подход, просто многие вызовы «методов» не имеют ничего общего с полиморфизмом.источник
Вы видите много наследования и полиморфизма в большинстве инструментов UI.
Например, в наборе инструментов JavaFX UI
Button
наследует, отButtonBase
чего наследует, отLabeled
которого наследует, отControl
которого наследует, отRegion
которого наследует, отParent
которого наследует, отNode
которого наследуетсяObject
. Многие слои перекрывают некоторые методы из предыдущих.Когда вы хотите, чтобы эта кнопка появлялась на экране, вы добавляете ее в a
Pane
, которая может принимать все, что унаследовано отNode
ребенка. Но как Pane узнает, что делать с Button, когда он просто видит ее как общий объект Node? Этот объект может быть чем угодно. Панель может сделать это, потому что Button переопределяет методы Node с помощью любой логики, специфичной для кнопки. Панель просто вызывает методы, определенные в Node, а остальное оставляет самому объекту. Это прекрасный пример прикладного полиморфизма.Инструментарий пользовательского интерфейса имеет очень большое значение в реальном мире, что делает его полезным для преподавания как по академическим, так и по практическим причинам.
Тем не менее, наборы инструментов для пользовательского интерфейса также имеют существенный недостаток: они, как правило, огромны . Когда инженер-программист-новичок пытается понять внутреннюю работу общей структуры пользовательского интерфейса, они часто сталкиваются с более чем сотней классов , большинство из которых служат очень эзотерическим целям. «Какого черта это
ReadOnlyJavaBeanLongPropertyBuilder
? Является ли это важно? У меня есть , чтобы понять , что это хорошо для?» Новички могут легко заблудиться в этой кроличьей норе. Поэтому они могут либо бежать в ужасе, либо остаться на поверхности, где они просто изучают синтаксис и стараются не слишком задумываться о том, что на самом деле происходит под капотом.источник
Хотя здесь уже есть хорошие примеры, другой пример - заменить животных устройствами:
Device
может бытьpowerOn()
,powerOff()
,setSleep()
а можетgetSerialNumber()
.SensorDevice
может сделать все это, а также обеспечить полиморфные функции , такие какgetMeasuredDimension()
,getMeasure()
,alertAt(threashhold)
иautoTest()
.getMeasure()
не будут реализованы одинаково для датчика температуры, детектора света, детектора звука или объемного датчика. И, конечно же, каждый из этих более специализированных датчиков может иметь некоторые дополнительные функции.источник
Презентация является очень распространенным приложением, возможно, наиболее распространенным является ToString (). В основном это Animal.Speak (): вы указываете объекту проявить себя.
Вообще говоря, вы говорите объекту «делать свое дело». Думайте Сохранить, Загрузить, Инициализировать, Удалить, ProcessData, GetStatus.
источник
Моим первым практическим использованием полиморфизма была реализация Heap в Java.
У меня был базовый класс с реализацией методов insert, removeTop, где разница между max и min Heap была бы только тем, как работает метод сравнения.
Поэтому, когда я хотел иметь MaxHeap и MinHeap, я мог просто использовать наследование.
источник
Вот реальный сценарий полиморфизма таблицы веб-приложения / базы данных :
Я использую Ruby on Rails для разработки веб-приложений, и одна из общих черт многих моих проектов - возможность загружать файлы (фотографии, PDF-файлы и т. Д.). Так, например, у a
User
может быть несколько изображений профиля, а такжеProduct
может быть много изображений продукта. Оба имеют поведение загрузки и хранения изображений, а также изменения размера, создания миниатюр и т. Д. Чтобы оставаться СУХИМЫМИ и делиться поведениемPicture
, мы хотим сделатьPicture
полиморфным, чтобы он мог принадлежать обоимUser
иProduct
.В Rails я бы проектировал свои модели так:
и миграция базы данных для создания
pictures
таблицы:Столбцы
imageable_id
иimageable_type
используются Rails внутри. По сути,imageable_type
содержит имя класса ("User"
,"Product"
и т. Д.) Иimageable_id
является идентификатором связанной записи. Такimageable_type = "User"
иimageable_id = 1
будет запись вusers
таблице сid = 1
.Это позволяет нам делать
user.pictures
доступ к фотографиям пользователя, а такжеproduct.pictures
получать изображения продукта. Затем все поведение, связанное с изображениями, инкапсулируется вPhoto
классе (а не в отдельном классе для каждой модели, для которой требуются фотографии), поэтому все остается СУХИМЫМ.More reading: Рельсы полиморфные ассоциации .
источник
Существует много доступных алгоритмов сортировки, таких как пузырьковая сортировка, вставка, быстрая сортировка, сортировка кучи и т. Д., И они имеют различную сложность, и какой из них оптимально использовать, зависит от различных факторов (например, размер массива)
Клиент, предоставленный с интерфейсом сортировки, заботится только о предоставлении массива в качестве входных данных, а затем получает отсортированный массив. Во время выполнения в зависимости от определенных факторов может быть использована соответствующая реализация сортировки. Это один из примеров реального использования полиморфизма.
То, что я описал выше, является примером полиморфизма во время выполнения, тогда как перегрузка метода является примером полиморфизма времени компиляции, где complier в зависимости от типов параметров i / p и o / p и количества параметров связывает вызывающую программу с правильным методом во время самого завершения.
Надеюсь, это проясняет.
источник