Форум программистов, компьютерный форум, киберфорум
ООП и паттерны
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.88/16: Рейтинг темы: голосов - 16, средняя оценка - 4.88
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1

Интересная заморочка возникла. Как реализовать нечно вроде "вывернутого полиморфизма"?

19.02.2013, 19:44. Показов 3524. Ответов 29
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
с "нормальным" все понятно: имея хэндл (или указатель) на базовый объект, вызывая виртуальный метод, мы получаем различное поведение, в зависимости от типа объекта, к которому привязан хэндл (на который указывает указатель).

а представим себе, что мы имеем хэндл базового класса, и хотим вызвать не его метод, а метод другого, "постороннего" класса, но не любой, а тот из перегруженных, который хочет получить объект именно того класса, который мы имеем в данный момент. немного запутанно, но ясно
короче, нужно выполнить downcast, тогда вызывать перегруженный метод другого класса, и все сработает.
мне ничего в голову не приходит (в данный момент с жавой), кроме instanceof. но "люди говорят", что если тебе понадобилось воспользоваться этой штукой, посмотри на свой дизайн, там что-то нехорошо пахнет. переделай и обойдешься без этого.

вот прошу рассказать, как такое правильно осуществить по части дизайна.

пример попробую привести:

имеется базовый класс "мясо", от него "конина", "говядина", "свинина".

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

"красивый дизайн" - это когда "мясо" само себя готовит. "повар" получает "мясо" и вызывает его метод "анудавай!", и получает нужный продукт. но тогда какой он повар? вот ему (или кому-то) распознавать, что за мясо, и тогда уже... а для этого нужно использовать instanceof. но это нехорошо пахнет... не принюхиваться, пусть только работает, или что делать?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
19.02.2013, 19:44
Ответы с готовыми решениями:

Возникла интересная идея...
Есть желание написать программу для живого общения с ОС...начать хочу с самого элементарного...например с коментирования ошибок,...

Когда Маша и Витя покупали подарок возникла интересная ситуация
Задача "Сдача" имя входного файла a.in имя выходного файла a.out ограничение 64мб Когда Маша и Витя покупали подарок возникла...

Интересная задачка. Как реализовать ?
Наткнулся на такую задачку. Поделитесь, пожалуйста, идеями по реализации Для нанесения на автомобильный номер можно использовать...

29
432 / 433 / 93
Регистрация: 16.07.2012
Сообщений: 886
19.02.2013, 20:23
Есть замечательная заметка - When Polymorphism Fails - рассматривающая именно такую ситуацию
1
 Аватар для Nagdiel
117 / 116 / 8
Регистрация: 23.12.2012
Сообщений: 195
20.02.2013, 00:25
Так вроде для такого случая есть паттерн Strategy

Кстати, похожий пример рассматривается в этой статье.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
20.02.2013, 08:16
Это мультиметоды называется, если я правильно понял суть проблемы.

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
(defgeneric cook (subject object dish))
 
(defclass cook () ())
 
(defclass meat () ())
(defclass beef (meat) ())
(defclass pork (meat) ())
 
(defmethod cook ((s cook) (o beef) (dish (eql :stroganoff)))
  (format t "Cooking beef stroganoff~%"))
 
(defmethod cook ((s cook) (o beef) (dish (eql :shashlik)))
  (format t "Cooking beef shashlik~%"))
 
(defmethod cook ((s cook) (o beef) dish)
  (format t "Cooking some beef dish (~a)~%" dish))
 
(defmethod cook ((s cook) (o pork) (dish (eql :shashlik)))
  (format t "Cooking pork shashlik~%"))
 
(defmethod cook ((s cook) (o pork) dish)
  (format t "Cooking some pork dish (~a)~%" dish))
 
 
 
(defun demo ()
  (let ((c (make-instance 'cook))
        (b (make-instance 'beef))
        (p (make-instance 'pork)))
    (cook c b :stroganoff)
    (cook c b :shashlik)
    (cook c b 'unknown)
    (cook c p :shashlik)
    (cook c p 'unknown)))
 
(demo)
 
; Cooking beef stroganoff
; Cooking beef shashlik
; Cooking some beef dish (UNKNOWN)
; Cooking pork shashlik
; Cooking some pork dish (UNKNOWN)
0
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
20.02.2013, 13:09  [ТС]
Цитата Сообщение от canopen Посмотреть сообщение
Есть замечательная заметка - When Polymorphism Fails - рассматривающая именно такую ситуацию
спасибо! очень интересная заметка. там рядом в блоге еще много других, сделал закладку, может еще что-то почитаю.

Добавлено через 37 минут
Цитата Сообщение от Nagdiel Посмотреть сообщение
Так вроде для такого случая есть паттерн Strategy
этот пэтэрн - не для нашего случая. это когда можно переложить работу с повара на мясо. т.е. мясо должно уметь само себя готовить. тогда нафига нам повар вообще?
0
1969 / 825 / 115
Регистрация: 01.10.2012
Сообщений: 4,899
Записей в блоге: 2
21.02.2013, 15:55
Цитата Сообщение от novi4ok Посмотреть сообщение
"красивый дизайн" - это когда "мясо" само себя готовит.
Это случай простой, стремиться к нему смысла нет - недостижимо. Продолжая Ваш пример: есть сущность "блюдо". Оно должно знать (и как-то общаться) с классом "повар" (всякий готовит по разному) и наследовать (или агрегировать) класс "мясо". Мне кажется что "блюдо" и должно рулить (оно знает как себя готовить) используя "повара" и "мясо"
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
21.02.2013, 18:29
Цитата Сообщение от Igor3D Посмотреть сообщение
Это случай простой, стремиться к нему смысла нет - недостижимо. Продолжая Ваш пример: есть сущность "блюдо". Оно должно знать (и как-то общаться) с классом "повар" (всякий готовит по разному) и наследовать (или агрегировать) класс "мясо". Мне кажется что "блюдо" и должно рулить (оно знает как себя готовить) используя "повара" и "мясо"
ООП это моделирование мира. И где вы видели блюдо, которое рулит поваром и мясом?

novi4ok, с чего это ты обобщил разные типы мяса? Вот если бы занимались перевозкой этого мяса, то скорее всего разницы в типе нет, а вот если что-то готовим, то тут уже нужно их различать
В этой книжке есть красивый прием позволяющий определять что за типы без всяких там dynamic_cast
0
1969 / 825 / 115
Регистрация: 01.10.2012
Сообщений: 4,899
Записей в блоге: 2
22.02.2013, 11:49
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
ООП это моделирование мира.
См библию
Суть моделирования реальности не в покорном следовании тому, что мы видим, а в использовании реальности как начала для проектирования,
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
22.02.2013, 12:38
источника вдохновения и как якоря, который удерживает, когда стихия программирования грозит лишить нас способности понимания своей собственной программы.
создание неестественных моделей, только способствуют к непониманию.
0
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
22.02.2013, 14:42
По-моему, здесь как раз подходит паттерн Посетитель (Visitor).

Блюдо как раз является "посетителем" объекта Повар. А Повар знает, как именно нужно обработать конкретное Блюдо, - имеет разные методы обработки для Гуляша и для Плова. Блюдо, соответственно, содержит нужное количество конкретных Продуктов. Ну и если Официант требует приготовить Блюдо "вообще" (Абстрактное Блюдо) - тупо ругается "Ну не знаю я, как готовить Абстрактное Блюдо!"

Нет?
0
1969 / 825 / 115
Регистрация: 01.10.2012
Сообщений: 4,899
Записей в блоге: 2
22.02.2013, 14:57
Цитата Сообщение от CheshireCat Посмотреть сообщение
Блюдо как раз является "посетителем" объекта Повар. А Повар знает, как именно нужно обработать конкретное Блюдо, - имеет разные методы обработки для Гуляша и для Плова.
Это вроде бы соответствует "реальному миру", но боюсь что при таком подходе весь ф-ционал сливается в класс Повар и появляется туча if'ов и/или switch
0
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
22.02.2013, 19:34  [ТС]
в конце-концов, только для классических задачек из учебника можно подобрать классический пэттэрн из учебника.
а реально решаемые задачи не всегда укладываются в "прокрустово ложе пэттэрнов", и нужно руководствоваться здравым смыслом и создавать свои собстсенные. представьте себе, что исчезли все учебники с пэттэрнами, и их создали группу, которая будет разрабатывать новые. уверены, что они создадут те же самые? мир наш сложнее пэттернов, и не всегда красиво формализуется.
конечно, если заранее известно, что мясо - только для того, чтобы из него что-нибудь готовить, то можно заранее (обязательно!) приложить рецепт, и повару не нужно будет знать подробности: он знает, что нужно их этого мяса достать бумажку и сделать все, что там написано. но если объекты уже есть, мы их не разрабадываем, и нам нужно их обрабатывать (или использовать для обработки) в зависимости от их типа, то не нужно стесняться, и писать instanceof столько раз, сколько производных классов нам известно. и да, если будут появляться новые - будем расширять, альтернативы не вижу.
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
22.02.2013, 20:37
Цитата Сообщение от Igor3D Посмотреть сообщение
Это вроде бы соответствует "реальному миру"
в каком месте соответствует?
Цитата Сообщение от novi4ok Посмотреть сообщение
в конце-концов, только для классических задачек из учебника можно подобрать классический пэттэрн из учебника.
твою задачку можно без паттерна решить.

Цитата Сообщение от novi4ok Посмотреть сообщение
что нужно их этого мяса достать бумажку и сделать все, что там написано.
Идея с рецептом верная, с бумажкой внутри мяса нет.
0
Модератор
 Аватар для TanaTiX
2936 / 1795 / 180
Регистрация: 19.02.2011
Сообщений: 6,552
22.02.2013, 21:23
Думаю, у поваров в голове множество if-ов и/или switch-case-ов.
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
22.02.2013, 21:32
TanaTiX, найди хотя бы один if/switch
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef CHEF_H
#define CHEF_H
 
#include <list>
 
class Product;
class Beef;
class Pig;
 
class Chef
{
public:
 
    void addProducts(std::list<Product*> products);
    void take(Beef* beef);
    void take(Pig* pig);
 
 
private:
 
    std::list<Beef*> beefs_;
    std::list<Pig*> pigs_;
 
};
#endif // CHEF_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include "chef.h"
#include "product.h"
 
 
void Chef::addProducts(std::list<Product*> products)
{
    for(Product* product: products)
        product->look(this);
}
 
void Chef::take(Beef* beef)
{
    std::cout<<"add beef"<<std::endl;
    beefs_.push_back(beef);
}
 
void Chef::take(Pig* pig)
{
    std::cout<<"add pig"<<std::endl;
    pigs_.push_back(pig);
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef PRODUCT_H
#define PRODUCT_H
 
class Chef;
class Product
{
public:
    virtual void look(Chef* chef) = 0;
};
 
class Flesh: public Product
{
};
 
class Beef: public Flesh
{
public:
    virtual void look(Chef* chef);
};
 
class Pig: public Flesh
{
public:
    virtual void look(Chef* chef);
};
 
#endif // PRODUCT_H
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include "product.h"
#include "chef.h"
 
void Beef::look(Chef* chef)
{
    chef->take(this);
}
 
void Pig::look(Chef* chef)
{
    chef->take(this);
}
0
Модератор
 Аватар для TanaTiX
2936 / 1795 / 180
Регистрация: 19.02.2011
Сообщений: 6,552
22.02.2013, 21:38
Dmitriy_M, в плюсах не шарю, но if/switch не нашел. И к чему мне это? Вы же мне не трепанацию черепа повара предлагаете сделать...
0
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
22.02.2013, 22:04  [ТС]
не годится. ты цель ставил не мою задачку решить, а без ифов обойтись. не важно, решение полезно или нет.
повар получает указатель на базовый класс, а мясо не знает вообще, что где-то сущетсвует повар.
т.е. повар получает три сорта мяса в одинаковых упаковках с надписью "мьасо", и в зависимости от того, что за сорт внутри, нужно принять решение. единственный вариант для повара это сделать - распечатать и посмотреть (т.е. instanceof), а потом "if ..."
0
1443 / 1326 / 131
Регистрация: 20.03.2009
Сообщений: 4,689
Записей в блоге: 11
22.02.2013, 22:34
Цитата Сообщение от novi4ok Посмотреть сообщение
распечатать и посмотреть
look и предназначен, для осмотра содержимого
Цитата Сообщение от novi4ok Посмотреть сообщение
не годится. ты цель ставил не мою задачку решить, а без ифов обойтись.
Цитата Сообщение от novi4ok Посмотреть сообщение
а представим себе, что мы имеем хэндл базового класса, и хотим вызвать не его метод, а метод другого, "постороннего" класса
C++
1
2
3
4
5
void Chef::take(Beef* beef)
{
    std::cout<<"add beef"<<std::endl;
    beef->some_method();
}
Цитата Сообщение от novi4ok Посмотреть сообщение
а мясо не знает вообще, что где-то сущетсвует повар.
C++
1
2
3
4
5
6
7
class Product
{
public:
    virtual void look(Chef* chef)
    {
    }
};
за счет forward declaration мясо знает, что есть некий Chef которого может быть, а может и не быть.

Цитата Сообщение от novi4ok Посмотреть сообщение
распечатать и посмотреть (т.е. instanceof), а потом "if ..."
Молодец. Жестко привязался к иерархии классов, если изменил иерархию, то все поломал.
К примеру соевое мясо, то же мясо?
0
556 / 510 / 25
Регистрация: 23.07.2009
Сообщений: 2,359
Записей в блоге: 1
23.02.2013, 01:53  [ТС]
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
C++
1
2
3
4
5
void Chef::take(Beef* beef)
{
    std::cout<<"add beef"<<std::endl;
    beef->some_method();
}
вот уперся! да не получает повар beef : public meat! он получает meat!
0
1969 / 825 / 115
Регистрация: 01.10.2012
Сообщений: 4,899
Записей в блоге: 2
23.02.2013, 10:25
Цитата Сообщение от Dmitriy_M Посмотреть сообщение
C++
1
    void addProducts(std::list<Product*> products);
Подавать контейнеры по значению не есть хорошо.

Цитата Сообщение от novi4ok Посмотреть сообщение
единственный вариант для повара это сделать - распечатать и посмотреть (т.е. instanceof), а потом "if ..."
Зависит от того какие задачи перед поваром. Напр возможно блюдо вызывает виртуальные методы повара для каждой фазы приготовления (варки, жарки и др)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.02.2013, 10:25
Помогаю со студенческими работами здесь

Реализовать сложение двух чисел (с использованием полиморфизма)
С++ Нужно реализовать сложение двух чисел в разных СС с помощью ПОЛИМОРФИЗМА Пожалуйста помогите

пожалуйста как реализовать стрельбу по полю что-то вроде морского боя Pascal ABC
так чтоб вводить координаты стрельбы и в этой точке отображались изменения uses crt; var razmer_k, kolvo_k, strokstolb :byte;...

Заморочка со значение поля textaria, может кто знает как исправить
в общем суть в том, что на сайте с помощью php через поле textaria можно редактировать некий контент.. записывать его туда в виде html...

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

Есть класс, допустим NP. Нужно реализовать что то вроде такого: $np = new NP(). $np->senders->get();
Доброго времени суток! Допустим есть класс np. Создаем экземпляр $np = new NP(); Далее я хочу реализовать вызов что то вроде такого:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек SDL3 и Box2D из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия SDL 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual. . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru