Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Системный анализ, проектирование и UML > Возможна ли замена типа поля у предков


Автор: AnTeml 16.7.2012, 09:18
Здравствуйте. Который раз уже наталкиваюсь на одну и ту же проблему. Особенно часто она возникает, когда сопровождаются две параллельные структуры.

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

Получается, у меня две параллельные структуры - структура классов контролов, которая развивается по своим законам и структура конкретных реализаций, которая местами схожа, а местами живёт совершенно своей жизнью

Проблема возникает на самом первом этапе:

Код

type
  TControlImp = class
    function Height: Integer; virtual; abstract; 
    function Width: Integer; virtual; abstract;
  end;

  TWindowImp = class(TControlImp)
    function IsFullScreen: Boolean; virtual; abstract;
  end;


  TMyControl = class
  private
    Imp: TControlImp;
  public
    function Height: Integer; //делегируются из Imp
    function Width: Integer; //делегируются из Imp
  end;

  TMyWindow = class(TMyControl)
    // private
    //   imp: TWindowImp; - хотелось бы что-то подобное. к тому же, TWindowImp - наследник TControlImp
  public
    function IsFullScreen: Boolean; //делегируется из Imp, но приходится использовать приведение классов
  end;

implementation

{ TMyControl }

function TMyControl.Height: Integer;
begin
  Result := imp.Height
end;

function TMyControl.Width: Integer;
begin
  Result := imp.Width
end;

{ TMyWindow }

function TMyWindow.IsFullScreen: Boolean;
begin
  Result := (imp as TWindowImp).IsFullScreen  // в исходном варианте приходится всюду приводить
end;


можно ли в классе TMyWindow - наследнике от TMyControl  под именем imp  использовать не TControlImp, а TWindowImp, который, в свою очередь, является наследником TControlImp?

Или без приведения типов тут никак не обойтись?

Вопрос интересует как по Delphi, так и по другим языкам, где как решается подобное?
Или можно структуры классов как-нибудь по-другому определить?

Автор: AnTeml 22.7.2012, 18:48
Мда, присмотрелся я к своей структуре, и понял, что структуру "имплементаций" так, как я создаю, создавать  нельзя - для каждого контрола должен быть отдельный объект, без какой-либо иерархии. Похоже, что так.

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

Автор: k0rvin 28.8.2012, 21:05
Че-то я нифига не понял. Обычно в таких случаях используют интерфейсы, что-то типа:

Код

type
  IMyControl = interface
  public
    property Height : Integer;
    property Width  : Integer;
  end;

  IMyWindow = interface (IMyControl)
  public
    property IsFullScreen : Boolean;
  end;

  TMyControlImp = class (IMyControl)
  private
    FHeight : Integer;
    FWidth  : Integer;
    function  GetWidth : Integer;
    procedure SetWidth (Integer);
  public
    property Height : Integer read FHeight  write FHeight; 
    property Width  : Integer read GetWidth write SetWidth;
  end;

  TMyWindowImp = class (TMyControlImp, IMyWindow)
  public
    property IsFullScreen : Boolean;
  end;

implementation

...

function TMyControlImp.GetWidth : Integer;
begin
  Result := FWidth;
end;

procedure TMyControlImp.SetWidth (NewWidth : Integer);
begin
  FWidth := NewWidth;
  WriteLn('Width setted to ', FWidth);
end;

end.


соответственно использовать примерно так

Код

procedure Move (Control : IMyControl; X, Y : Integer);
begin
  Control.X := X;
  Control.Y := Y;
end;

...

var
  MyControl : IMyControl;
  MyWindow  : IMyWindow;

MyControl := TMyControlImp.Create;
MyWindow  := TMyWindowImp.Create;

Move(MyControl, 1, 2);
Move(MyWindow,  3, 4);


Или я чего-то не понял?

В общем-то можно обойтись и без интерфейсов, но с ними гибче.

Автор: AnTeml 31.8.2012, 13:37
Вот честно, интерфейсы практически не использовал, знаком только с общими понятиями. 

Однако, думаю, я имел в виду несколько другое.

Класс MyControlImp (реализация контрола) ничего не знает о MyControl, так же и MyWindowImp ничего не знает о существовании MyWindow
Реализация - это реализация базового функционала, на котором основывается главный класс

Например, MyWindowImp умеет отображать окно в нужном месте, а MyWindow умеет танцевать (вызывая в определённом порядке метод отображения), и MyWindowImp не должен наследоваться от MyWindow - он ничего не должен знать о танцах, в MyWindowImp реализуют отображение в заданной точке для определённой операционной системы, например

ЗЫ как раз вернулся с отпуска, сегодня засел за эту задачу. Отпишусь по результатам smile

Автор: k0rvin 1.9.2012, 10:02
Цитата(AnTeml @ 31.8.2012,  13:37)
Класс MyControlImp (реализация контрола) ничего не знает о MyControl, так же и MyWindowImp ничего не знает о существовании MyWindow
Реализация - это реализация базового функционала, на котором основывается главный класс

Ну значит наоборот, MyControlImp -- базовый, а MyControl -- дочерний. В общем-то посмотри иерархию классов VCL.

Автор: AnTeml 3.9.2012, 03:55
Цитата(k0rvin @  1.9.2012,  10:02 Найти цитируемый пост)
Ну значит наоборот, MyControlImp -- базовый, а MyControl -- дочерний
В таком случае я не смогу сменить реализацию без перекомпиляции минимум. В этом и суть "моста", когда "лёгким движением руки" в твоей программе все объекты (в моём случае - контролы) начинают выглядеть (реализовываться) по-другому.  Например, были окна VCL - стали FMX, и не нужна не то что перекомпиляция - можно переключать реализации динамически, а классы Implementation собраны в одном месте (модуле).

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)