Форум программистов, компьютерный форум, киберфорум
ООП и паттерны
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
 Аватар для snake32
3511 / 1694 / 236
Регистрация: 26.02.2009
Сообщений: 8,471
Записей в блоге: 6

ООП без множественного наследования

04.09.2014, 15:22. Показов 1392. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени!

Нужно посчитать поля от станции в точках. Расчёт может производиться как классическим методом, так и с помощью OpenCL. То есть на разных платформах.
Так же существуют разные алгоритмы вычисления полей. Что бы уметь считать например на 2х алгоритмах, нужно написать 4 класса: 2 на CL реализацию и 2 на обычную.

В итоге получилось такое наследование:
Delphi
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
type
TFields = class // базовый класс содержит: 
  property RXcoord:TArray<TDVec2>; // координаты точек
  property TXcoord:TDVec2;          // координата станции
  property E:TArray<double>;        // поля
  procedure Update; virtual; abstract;
end; 
 
TPureFieldsА = class( TFields ) // расчёт по алгоритму А на CPU
  property ParamA; // все параметры расчёта для А алгоритма
  procedure Update; override;
end;
 
TPureFieldsB = class( TPureFieldsA ) // расчёт по алгоритму B на CPU
  property ParamB; // все параметры расчёта для B алгоритма
  procedure Update; override;
end;
 
TCLFiledsA = class( TFields ) // расчёт по алгоритму А на OpenCL
  property ParamA; // все параметры расчёта для А алгоритма
  procedure Update; override;
end;
 
TCLFiledsB = class( TCLFieldsA ) // расчёт по алгоритму B на OpenCL
  property ParamB; // все параметры расчёта для B алгоритма
  procedure Update; override;
end;
ParamA и ParamB это на самом деле группа параметров соответственно для A и B алгоритмов.
Как видно свойства параметров расчёта приходится дублировать. Что не есть хорошо.

А что если создать класс параметров и объявить его базовом классе?

Delphi
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
type
  TParam = class // абстрактный класс параметров
    ProfileStep:double
  end;
 
  TParamA = class( TParam )
    property EnableWater:Boolean;
    // и ещё куча параметров
  end;
 
  TParamB = class( TParamA )
    property HRX:double;
    // и ещё куча параметров
  end;
 
  TFields = class // базовый класс содержит:
   private
     FParam:TParam;
   protected 
    property RXcoord:TArray<TDVec2>; // координаты точек
    property TXcoord:TDVec2;          // координата станции
    property E:TArray<double>;        // поля
    property Params:TParam read FParam write SetParam
    procedure Update; virtual; abstract;
  end;
 
  TPureFieldsА = class( TFields ) // расчёт по алгоритму А на CPU
    procedure Update; override;
  end;
 
  TPureFieldsB = class( TPureFieldsA ) // расчёт по алгоритму B на CPU
    procedure Update; override;
  end;
 
  TCLFiledsA = class( TFields ) // расчёт по алгоритму А на OpenCL
    procedure Update; override;
  end;
 
  TCLFiledsB = class( TCLFieldsA ) // расчёт по алгоритму B на OpenCL
    procedure Update; override;
  end;
Вроде бы всё норм и не нужно дублировать параметры, достаточно подставить нужный класс параметров.
НО, опять засада:
Внутри TCLFiledsB.Update да и во всех вспомогательных методах этого класса нужно будет явно приводить Params из базового класса TParam в TParamB чтобы получить доступ к нужным мне полям. Что опять не есть хорошо.

Так как мне быть?

ЗЫ: интерфейсы не предлагать, хочется попробовать найти решение без них.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
04.09.2014, 15:22
Ответы с готовыми решениями:

Делема множественного наследования
Все перерыл, уже начинаю думать, что это косяк С#. есть 3 интерфейса A B C и 2 класса 1 класс наследник от A B 2 класс наследник от...

Отсутствие множественного наследования
Добрый день! У меня есть интерфейс GeometryObject, описывающий геометрические фигуры. От него наследуются такие классы как: Point и Line, и...

Иерархия множественного наследования и шаблон
Имеется абстрактный класс Playerpublic abstract class Player {...}от него наследую 2 класса: User и Computerpublic class User : Player...

9
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
04.09.2014, 15:59
Что-то я не понимаю, зачем ты *B-классы наследуешь от *A-классов?

Может так:
Delphi
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
TFields = class
    property RXcoord: TArray<TDVec2>;
    property TXcoord: TDVec2;
    property E: TArray<Double>;
    procedure Update; virtual; abstract;
end;
 
TFieldsA = class(TFields)
    property ParamA;
end;
 
TFieldsB = class(TFields)
    property ParamB;
end;
 
TPureFieldsA = class(TFieldsA)
    procedure Update; override;
end;
 
TPureFieldsB = class(TFieldsB)
    procedure Update; override;
end;
 
TCLFieldsA = class(TFieldsA)
    procedure Update; override;
end;
 
TCLFieldsB = class(TFieldsB)
    procedure Update; override;
end;
?
0
 Аватар для snake32
3511 / 1694 / 236
Регистрация: 26.02.2009
Сообщений: 8,471
Записей в блоге: 6
04.09.2014, 16:44  [ТС]
Цитата Сообщение от korvin_ Посмотреть сообщение
зачем ты *B-классы наследуешь от *A-классов?
Потому что B-алгоритм использует большинство ф-ии из A алгоритма, которые дублировать тем более не хочется.
Цитата Сообщение от korvin_ Посмотреть сообщение
Может так:?
Так теряются наработки предыдущего алгоритма-предка =(.

Пробовал без классов: получаются ф-ии с кучей параметров. То есть появляются не только расчётные параметры, но и "промежуточные" данные, которых тоже не мало.
0
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
04.09.2014, 17:44
Цитата Сообщение от snake32 Посмотреть сообщение
Потому что B-алгоритм использует большинство ф-ии из A алгоритма, которые дублировать тем более не хочется.
Цитата Сообщение от snake32 Посмотреть сообщение
Так теряются наработки предыдущего алгоритма-предка =(.
Ну смени пару строк а ляПардон, затупил.

Добавлено через 28 минут
Цитата Сообщение от snake32 Посмотреть сообщение
Потому что B-алгоритм использует большинство ф-ии из A алгоритма, которые дублировать тем более не хочется.
Ну тогда, как вариант просто вынести параметры в промежуточные классы, чтоб не дублировать их все, а создать переменную класса, типа

Delphi
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
TFields = class
    property RXcoord: TArray<TDVec2>;
    property TXcoord: TDVec2;
    property E: TArray<Double>;
end;
 
TFieldsA = class
    property ParamA;
    ...
end;
 
TFieldsB = class
    property ParamB;
    ...
end;
 
TCalc = class
    procedure Update; virtual; abstract;
end;
 
TPureCalcA = class(TCalc)
    property Params:  TFields;
    property ParamsA: TFieldsA;
    procedure Update; override;
end;
 
TPureCalcB = class(TPureCalcA)
    property ParamsB: TFieldsB;
    procedure Update; override;
end;
 
TCLCalcA = class(TCalc)
    property Params:  TFields;
    property ParamsA: TFieldsA;
    procedure Update; override;
end;
 
TCLCalcB = class(TCLCalcA)
    property ParamsB: TFieldsB;
    procedure Update; override;
end;
?
0
 Аватар для snake32
3511 / 1694 / 236
Регистрация: 26.02.2009
Сообщений: 8,471
Записей в блоге: 6
05.09.2014, 10:09  [ТС]
Хм. Короче пока остановился на втором варианте с явным приведением типа. То есть в каждом TFields-классе, определяю своё свойство Params нужного мне типа, которое автоматически перекрывает свойство предка.

Сейчас напишу в Delphi разделе ссылку сюда. Хочется посмотреть как бы выглядело это дело с интерфейсам.
0
 Аватар для pHOMM
480 / 253 / 51
Регистрация: 30.06.2010
Сообщений: 651
05.09.2014, 11:31
Недавно решал подобную задачу, пока не допетрил, как сделать без дублирования и дублирование на уровне вызовов ещё осталось (но дублирование реализации почти удалось убрать). Пока ещё не пропали надежды изложить это через агрегацию.
Задача была такая
есть 2 класса (хоть и с общим предком но это не суть), которые имеют в себе много всякой реализации. от них требовалось породить по одному потомку, которые бы выполняли одну задачу (внешне), но опирались в работе на методы своих предков (и частично на свои данные, которые как раз дублируются).
Сделал так - написал интерфейс для общей задачи. Написал класс, реализующий этот интерфейс, у вышеозначенных потомков сделал поле такого класса, и самих этих потомков указал как реализующих данный интерфейс. В потомках пришлось методы интерфейса протянуть в вызовы к вложенному полю (реализатору работы). Открыл доку, сел тыкать директиву implements, она - то, что надо, хотел было применить её, но с наскоку не получилось, т.к. она содержит какой-то оверхед по использованию TAggregatedObject и я его не осилил тогда.
Могу дать ссылки на статьи, которые использовал для разбора этого дела.

Чисто для проформы - не знаю, мб упустили из виду - если использовано явное приведение, не обязательно ведь тащить во все методы, достаточно задекларить проперти этого типа и read FBaseParamObject

Ну и насчёт интерфейсов, написать через них можно, но, скорее всего, как и в моём случае, часть именно реализации придётся дублировать (интерфейс это ведь только контракт).
А вообще эта задача из области Аспектно-ориентированного программирования, и возможно его средства, в частности, атрибуты, могут дать способы решения.
1
 Аватар для snake32
3511 / 1694 / 236
Регистрация: 26.02.2009
Сообщений: 8,471
Записей в блоге: 6
05.09.2014, 14:01  [ТС]
Цитата Сообщение от pHOMM Посмотреть сообщение
Могу дать ссылки на статьи, которые использовал для разбора этого дела.
Да, было бы не плохо.
Цитата Сообщение от pHOMM Посмотреть сообщение
если использовано явное приведение, не обязательно ведь тащить во все методы, достаточно задекларить проперти этого типа и read FBaseParamObject
Дык так и делаю, Но всё равно в каждом классе приходится писать SetParams, GetParams свои так как тип свойства Params отличаются.

Цитата Сообщение от pHOMM Посмотреть сообщение
Ну и насчёт интерфейсов, написать через них можно, но, скорее всего, как и в моём случае, часть именно реализации придётся дублировать (интерфейс это ведь только контракт).
А вообще эта задача из области Аспектно-ориентированного программирования, и возможно его средства, в частности, атрибуты, могут дать способы решения.
Если речь идёт об атрибутах которые TCustomAttribut. То там вроде можно только на целый класс сделать атрибут, А мне надо на каждый экземпляр класса свою копию со своими данными
0
Модератор
 Аватар для FIL
3492 / 2614 / 742
Регистрация: 19.09.2012
Сообщений: 7,977
09.09.2014, 12:05
Такой вариант не подойдет?:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TPureFieldsА = class( TFields ) // расчёт по алгоритму А на CPU
  property ParamA; // все параметры расчёта для А алгоритма
  procedure Update; override;
end;
 
TPureFieldsB = class( TPureFieldsA ) // расчёт по алгоритму B на CPU
  property ParamB; // все параметры расчёта для B алгоритма
  procedure Update; override;
end;
 
TCLFiledsA = class( TPureFieldsА ) // расчёт по алгоритму А на OpenCL
  procedure Update; override;
end;
 
TCLFiledsB = class( TPureFieldsB ) // расчёт по алгоритму B на OpenCL
  procedure Update; override;
end;
0
 Аватар для snake32
3511 / 1694 / 236
Регистрация: 26.02.2009
Сообщений: 8,471
Записей в блоге: 6
09.09.2014, 14:31  [ТС]
Цитата Сообщение от FIL Посмотреть сообщение
Такой вариант не подойдет?:
Нет. TCLB должен наследоваться от TCLA так как там много общего(данные и методы)
Пока сделал так:
Delphi
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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
type
TParam = class
end;
 
TFields = class
private
  FParam:TParam;
protected
  function GetBaseParams:TParam;
  procedure SetBaseParams( const value:TParam );
public
  property Param:TParam read GetBaseParams write SetBaseParams;
  procedure Update; virtual; abstract;
end;
 
TParamA = class( TParam )
  // тут добавляются несколько свойств для алгоритма А
end;
 
TPureA = class( TFields )
private
   function GetParams:TParamA;
   procedure SetParams( const value:TParamA );
protected
  FDA:TArray<double>;
  FPGW:TArray<TDVec2>;
public
  property Param:TParamA read GetParams write SetParams;
  procedure Update; override;
end;
 
TCLA = class( TFields )
private
   function GetParams:TParamA;
   procedure SetParams( const value:TParamA );
protected
  FDA,FPGW:CLMem;// по сути это те же массивы как и в TPureA только на GPU
public
  property Param:TParamA read GetParams write SetParams;
  procedure Update; override;  
end;
 
TParamB = class( TParamA )
  // ещё несколько свойств для алгоритма В
end;
 
TPureB = class( TPureA )
private
   function GetParams:TParamB;
   procedure SetParams( const value:TParamB );
potected
  FRXtca,FTXtca:TArray<double>;
public
  property Param:TParamB read GetParams write SetParams;
  procedure Update; override;
end;
 
TCLB = class( TCLA )
private
   function GetParams:TParamB;
   procedure SetParams( const value:TParamB );
protected
  FRXtca,FTXtca:CLMem;// по сути это те же массивы как и в TPureB только на GPU
public
  property Param:TParamB read GetParams write SetParams;
  procedure Update; override;
end;
 
implementation
 
function TFields.GetBaseParams:TParam;
begin
  Result := FParam;
end;
procedure TFields.SetBaseParams( const value:TParam );
begin
  FParam := value;
end;
 
// здесь явно преобразую из базового типа и обратно
function TPureA.GetParams:TParamA;
begin
  Result := TParamA( GetBaseParams );
end;
procedure TPureA.SetParams( const value:TParamA );
begin
  SetBaseParam( value );
end;
// ну и так далее
function TCLA.GetParams:TParamA;
begin
  Result := TParamA( GetBaseParams );
end;
procedure TCLA.SetParams( const value:TParamA );
begin
  SetBaseParam( value );
end;
 
function TPureB.GetParams:TParamB;
begin
  Result := TParamB( GetBaseParams );
end;
procedure TPureB.SetParams( const value:TParamB );
begin
  SetBaseParam( value );
end;
 
function TCLB.GetParams:TParamB;
begin
  Result := TParamB( GetBaseParams );
end;
procedure TCLB.SetParams( const value:TParamB );
begin
  SetBaseParam( value );
end;
Каждый новый класс содержит лишь одну ссылку на параметры. A свойство Param предоставляет их в нужном типе. Единственное, нужно следить чтобы был установлен нужный тип параметров.
0
 Аватар для pHOMM
480 / 253 / 51
Регистрация: 30.06.2010
Сообщений: 651
10.09.2014, 21:31
http://stackoverflow.com/quest... implements
{ссылка удалена}
Вот парочка , в основном про директиву implements

По самим интерфейсам сперва dk потом rsdn
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.09.2014, 21:31
Помогаю со студенческими работами здесь

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

Использование интерфейсов вместо множественного наследования
У меня есть несколько свинговских форм, все они наследуют JFrame, т.е. наследовать больше я ничего не могу. Но в эти несколько форм хорошо...

Две игры на принципах множественного наследования
Нужно создать две игры, используя общую иерархию классов. Игра (крестики-нолики) должна быть с общим полем для двух игроков, а вторая...

Из этой программы нужно: разработать алгоритм и создать программу с применением множественного наследования
Из этой программы нужно: разработать алгоритм и создать программу с применением множественного наследования. При выполнении данного задания...

На основе указанных классов создать набор классов с использованием множественного наследования
Создать базовый класс «Транспорт» и производные от него классы «Автомобиль», «Поезд», «Самолет». Создать базовый класс «Тип» и производные...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Ритм жизни
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