Как сделать это ОО? - PullRequest
       12

Как сделать это ОО?

1 голос
/ 09 апреля 2010

Извините за плохой титул, я новичок в ООП, поэтому я не знаю, что означает то, что мне нужно сделать.

У меня есть, скажем, 10 различных объектов, которые наследуют один объект. У них разное количество и тип членов класса, но у всех них есть одно общее свойство - Visible.

type TSObject=class(TObject);
  protected
    Visible:boolean;
  end;

type
  TObj1=class(TSObject)
  private 
    a:integer;
    ...(More members)
end;
  TObj2=class(TSObject)
  private 
    b:String;
    ...(More members)
end;

...(Other 8 objects)

Для каждого из них у меня есть переменная.

var Obj1:TObj1;
    Obj2:TObj2;
    Obj3:TObj3;
    ....(Other 7 objects)

Правило 1: Только один объект может быть инициализирован за один раз (другие должны быть освобождены), чтобы быть видимым.

Для этого правила у меня есть глобальная переменная

var CurrentVisibleObj:TSObject; //Because they all inherit TSObject

Наконец, существует процедура, которая меняет видимость.

procedure ChangeObjVisibility(newObj:TSObject);
begin
  CurrentVisibleObj.Free; //Free the old object
  CurrentVisibleObj:=newObj; //assign the new object
  CurrentVisibleObj:= ??? //Create new object
  CurrentVisibleObj.Visible:=true; //Set visibility to new object
end;

Есть моя проблема, я не знаю, как ее инициализировать, потому что производный класс неизвестен (TObj1, TObj2, Tobj3 ... Какой?).

Как мне это сделать?

Я упростил объяснение, в проекте есть TFrames, каждый из которых имеет разные элементы управления, и я должен установить видимый / не видимый одинаково (оставив только один инициализированный кадр).

Извините за заголовок, я очень новичок в ООП.

Ответы [ 5 ]

1 голос
/ 09 апреля 2010

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

ChangeObjVisibility(Obj3);

Здесь, если Obj3 равен нулю (или, что еще хуже, является висящим указателем), ChangeObjVisibility не может узнать, какой тип объекта ему нужно создать.

Один из способов получить класс frame для создания - с помощью массива const или функции с регистром.

type
  TSObjectClass = class of TSObject;
const
  ObjectClasses = array[0..X] of TSObjectClass = (TObj1, TObj2, TObj3, ...)

function GetFrameclass(Index : Integer) : TSObjectClass;
begin
  Result := ObjectClasses[Index]

  OR 

  case Index of
    0 : Result := TObj1;
    1 : Result := TObj2;
    (...)
  end;
end;

Это будет работать, если фрейм не нуждается в какой-либо специальной инициализации.

Далее вы могли бы позвонить, как этот:

procedure ChangeCurrentFrame(NewFrameIndex : Integer);
var FrameClass : TSObjectclass;
    vFrame : TSObject;
begin
  FrameClass := GetFrameClass(NewFrameIndex);
  if CurrentVisibleObj.ClassType <> FrameClass then
  begin
    vFrame := FrameClass.Create(nil);
    SetCurrentFrame(vFrame);
  end;
end;

procedure SetCurrentFrame(newObj:TSObject); 
begin 
  if Assigned(CurrentVisibleObj) then
    CurrentVisibleObj.Free; //Free the old object 
  CurrentVisibleObj:=newObj; //assign the new object 
  if Assigned(CurrentVisibleObj) then
    CurrentVisibleObj.Visible:=true; //Set visibility to new object 
end; 

Здесь SetCurrentFrame заменяет вас ChangeObjVisibility (здесь вы действительно меняете текущий кадр, изменение видимости - это просто «побочный эффект»)

1 голос
/ 09 апреля 2010

Есть моя проблема, я не знаю как инициализировать его, потому что производная класс неизвестно (TObj1, TObj2, Tobj3 ... Какие один?).

Ну, в основном есть два варианта:

  • либо вы передаете тип объекта, который будет создан, в качестве параметра для вашего метода, например вызывающий должен сказать вам, что он хочет создать

  • вы можете определить, какой тип создать из некоторой другой информации; одним простым способом было бы создать объект того же типа, что и тот, который вы изначально передали (не знаю, имеет ли это смысл в вашем контексте)

Прошло много времени с тех пор, как я проделал какую-то серьезную работу с Delphi, но мне кажется, что я смутно помню, что в Delphi есть способ выразить «тип», который вы хотите иметь. Или, возможно, вы даже можете создать экземпляр данного типа на основе имени типа в виде строки (например, создать экземпляр TObj2 на основе передаваемой строки "TObj2")

1 голос
/ 09 апреля 2010

Если речь идет о группе элементов управления TFrame, и вы хотите, чтобы за один раз был виден только один из них, вам не нужно постоянно освобождать и создавать их. Вы можете просто поместить каждый кадр на одну страницу TPageControl, затем скрыть полосу вкладок и изменить видимый кадр, используя свойство ActivePage TPageControl.

0 голосов
/ 09 апреля 2010

Не следует создавать и освобождать свои кадры каждый раз, когда вы хотите изменить их видимость - все они всегда должны быть инициализированы.

0 голосов
/ 09 апреля 2010

Вы можете получить доступ к базовому свойству даже для производного объекта из-за отношения is-a. В вашем случае вы хотите иметь общее состояние для нескольких объектов, один из способов подумать об этом - создать класс менеджера, который будет содержать объекты. В качестве видимого объекта будет выбран только один объект. Возможно, вам не нужно свойство visible для содержащихся объектов, но этот дизайн также допускает это.

Контейнер

Список MyObjects; Объект MyVisibleObject;

...