Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / классовые константы дочернего объекта / 16 сообщений из 16, страница 1 из 1
10.08.2017, 19:37:20
    #39503689
Arshehremen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Пытаюсь написать нинзя код, что бы функция возвращала классовую константа дочернего класса, но ни так ни эдак не получается:

Код: pascal
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.
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TBase = class
    const Svalue='text';
    class function TakeName:string; virtual;
  end;


  TBook = class(TBase)
    const Svalue='book';
  //  class function TakeName:string;  override;
  end;

  TDog = class(TBase)
    const Svalue='dog';
 //   class function TakeName:string;   override;
  end;


  well = class of TBase ; //


var
  Form1: TForm1;
  AsWell:well;

implementation

{$R *.dfm}

 class function TBase.TakeName:string;    
        begin
            Result:=  SValue; 
        end;


 {class function TBook.TakeName:string;
        begin
            Result:=Svalue;
        end;

 class function TDog.TakeName:string;
        begin
            Result:=Svalue;
        end;  }

procedure TForm1.Button1Click(Sender: TObject);
begin
    AsWell :=TBook ;
    form1.Caption:=aswell. TakeName;
    //form1.Caption:=aswell. Svalue;  - так тоже не работает =(
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
    AsWell :=TDog ;
    form1.Caption:=AsWell. TakeName;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
    AsWell := TBase ;
    form1.Caption:=AsWell. TakeName;
end;

end.



цель, что бы по кнопки Button1Click и Button2Click записывали в заголовок формы книгу и собаку соответственно, и при этом не хоца плодить виртуальные методы в каждом дочернем классе.
...
Рейтинг: 0 / 0
10.08.2017, 19:46:19
    #39503696
alekcvp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Arshehremen,
Я когда-то пытался так делать, не работает. В каком классе метод - из того класса и константа будет.
...
Рейтинг: 0 / 0
10.08.2017, 20:24:32
    #39503713
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
используй классовую переменную, а константу в нее грузи из классового конструктора
...
Рейтинг: 0 / 0
10.08.2017, 21:18:20
    #39503730
schi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Константы не являются виртуальными. В дочерних классах появляется свой экземпляр SValue, про который базовый класс и его виртуальный метод не знают ничего.
...
Рейтинг: 0 / 0
11.08.2017, 06:33:47
    #39503776
Pu4koff
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Вроде бы начиная с 2010 версии появились атрибуты. Можно через них сделать.
...
Рейтинг: 0 / 0
11.08.2017, 11:37:13
    #39503927
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Pu4koff,

доступ к аттрибутам не так, чтобы быстрый. Далеко не всё в них можно перевести.

....жаль, что классовые конструкторы не виртуальны...
...
Рейтинг: 0 / 0
11.08.2017, 12:10:59
    #39503951
Bred eFeM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Arshehremen, так пойдёт:?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
class function TBase.Cname: String;
begin
 Result := Self.ClassName;
end;

class function TBase.Cconst: Integer;
begin
      if Self = TBase then Result := 1
 else if Self = TBook then Result := 2
 else if Self = TDog  then Result := 3
 else                      Result := 0;
end;


Arioch....жаль, что классовые конструкторы не виртуальны...Это как?
...
Рейтинг: 0 / 0
11.08.2017, 14:02:17
    #39504084
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
сделай ридонли свойство вместо константы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.08.2017, 14:39:29
    #39504118
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Мимопроходящий> сделай ридонли свойство вместо константы.

А толку-то? Заполнять-то его всё равно где-то
надо, в конструкторе, методе или ещё где.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
11.08.2017, 14:48:32
    #39504127
Vizit0r
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Arioch....жаль, что классовые конструкторы не виртуальны...
зато из конструктора запросто вызывается виртуальный метод. Проблема-то в чем?
...
Рейтинг: 0 / 0
13.08.2017, 00:12:12
    #39504497
Arshehremen
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Суть в том, что бы возвращать несколько параметров класса (около 10) без выделения памяти на экземпляр класса. В одном(это принципиально) месте в коде добавляется ссылка на класс и больше в модуле он нигде не должен фигурировать, даже, Bred eFeM , в виде строки.

Код: pascal
1.
2.
3.
4.
5.
 
ObjectTypes := TTypesList.Create ;//TTypesList это TList

      {$ifdef Tree}      objectTypes.Add(TTree);       {$endif}
      {$ifdef Horizon} objectTypes.Add(THorizon);  {$endif} //и ещё овер 9000 таких классов с одинаковым родителем.



До этого список параметров для каждого класса был в TTypesList(модифицированный TList) и они заполнялись из общего модуля. Но в итоге оказалось не очень удачным решением.

Так как с классовыми константами фича не удалась, решил использовать классовые функции в каждом экземпляре. Не радует только то, что в каждый дочерний класс надо тянуть статичный кусок кода с этими функциями.

Код: pascal
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.
THorizon = class(TSuperObject)                      //класс объекта горизонта

//...

        const
          ObjectName = 3;// 'Горизонт';
          PathName   = 4;
          StyleName  = 5;

//...


       ///<summary> Возвращает название типа объекта </summary>
       class function TakeInfoName          :string;  override;
       ///<summary> Возвращает группу типа объекта </summary>
       class function TakeInfoGroup          :string;  override;
end;

//...

class function THorizon.TakeInfoName          :string;
       begin
           result:=CurrentLocalisation[ObjectName];
       end;

class function THorizon.TakeInfoGroup          :string;
       begin
           result:=CurrentLocalisation[PathName];
       end;
...
Рейтинг: 0 / 0
13.08.2017, 10:16:43
    #39504530
schi
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
...
Рейтинг: 0 / 0
13.08.2017, 17:22:51
    #39504607
Bred eFeM
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Arshehremen возвращать несколько параметров класса (около 10) без выделения памяти на экземпляр класса. В одном(это принципиально) месте в коде
Код: pascal
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.
type
 TStrs = (csName, csPath, csInfo );
 TNums = (cnDef,  cnMin,  cnMax  );

 TType = class of TBase;
 PConst = ^TConst;
 TConst = record
  cType : TType;
  cStrs : array [TStrs] of String;
  cNums : array [TNums] of Integer;
 end;

 TBase = class
  public class function Cconst():PConst; 
 end;
 TBook = class(TBase) end;
 TDog =  class(TBase) end;

// ---------------------------------------------------------------------------------------

function Cconst(aType : TType): PConst;                           // odno mesto a
const
 cOver = 3;                                                       // 9000
type
 TConsts = array [0..cOver] of TConst;
const
 cAll : TConsts = ( (cType : nil;
                     cStrs : ('','','');
                     cNums : (0,0,0);                    ),

                    (cType : TBase;
                     cStrs : ('Base', 'c;\', 'Text');
                     cNums : (0, -100, 100);             ),

                    (cType : TBook;
                     cStrs : ('Book', 'd:\', 'Memo');
                     cNums : (42, 1, 10000);             ),

                    (cType : TDog;
                     cStrs : ('Dog', 'e:\', 'Note');
                     cNums : (4, 1, 100);                ) );
var
 i : Integer;
begin
 for i := Low(cAll) to High(cAll) do
  if aType = cAll[i].cType
   then Exit(@cAll[i]);
 Exit(@cAll[0]);
end;

class function TBase.Cconst: PConst;
begin
 Result := UnitName.Cconst(Self);                                 // TypeOf(Self) -> TType !
end;

// -----------------------------------------------------------------------------------------

procedure Cdemo;
var
 T : TType;
begin
                                                                  // x )
  with TBase.Cconst^ do begin
   Writeln ( cStrs[csName] );
   Writeln ( cNums[cnDef] );
  end;
                                                                  // y )
  with Cconst(TBook)^ do begin
   Writeln ( cStrs[csName] );
   Writeln ( cNums[cnDef] );
  end;
                                                                  // z )
  T := TDog;                                                      // odno mesto b
  with T.Cconst^ do begin
   Writeln ( cStrs[csName] );
   Writeln ( cNums[cnDef] );
  end;
end;

...
Рейтинг: 0 / 0
14.08.2017, 12:22:13
    #39504893
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Vizit0rArioch....жаль, что классовые конструкторы не виртуальны...
зато из конструктора запросто вызывается виртуальный метод. Проблема-то в чем?

Bred eFeMArioch....жаль, что классовые конструкторы не виртуальны...Это как?

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
type TBaseAPI = class
  protected
     Implementations: TList<TBaseAPI>;
.....
  class procedure Register;
  class constructor CreateList; {virtual - или static, неи разницы}
.....

class procedure TBaseAPI.Register;
begin
   Implementations.Add( Self );
end;

class constructor TBaseAPI.CreateList;
begin
   if nil = Implementations then 
     Implementations:= TList<TBaseAPI>.Create;

   Register;
end;



Пока все хорошо, казалось бы...

Начинаем в разных модулях делать разные реализации.

Код: pascal
1.
2.
3.
type TImplAAA = class(TBaseAPI) .... end;
type TImplBBB = class(TBaseAPI) .... end;
type TImplCCC = class(TBaseAPI) .... end;



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

Но "Волобуев, вот ваш меч". Для TImpl??? придется заводить классовые конструкторы-пустышки с единственной задачей - вызвать Inherited CreateList; Plumbing, plumbing, plumbing....
...
Рейтинг: 0 / 0
14.08.2017, 12:43:35
    #39504907
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Arshehremenнадо тянуть статичный кусок кода с этими функциями.

Функций много?

Сделай классовую переменную (в каждом классе) "указатель на данные".
С общим lazy-инициализатором. Если переменная nil, то создаем такие данные и заполняем их из, например, аттрибутов класса. Один раз - не тормозит.

Потребуются две виртуальных классовых функции - прочитать переменную и записать переменную.
Поскольку переменные будут разные, насколько я понимаю, объявлять их придется врозь.
И эти две функции придется копипастить, да. Но только их.

Код: pascal
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.
TBase = class
  protected 
   class var ClassData: PDataRecord;
   class var DataPointersToFree: TList;
   class function PlainReadDataRecord: PDataRecord; virtual;
   class procedure PlainSaveDataRecord( const ptr: PDataRecord ); virtual;

   class function GetDataRecord: PDataRecord;
 
   class constructor ClaCreate;
   class constructor ClaDestroy;

 public
   class function GetXXXX: string;
   class function GetYYYY: integer;
.....

class function TBase.GetXXXX: string;
begin
   Result := GetDataRecord.XXXX;
end;

class function TBase.GetYYYY: integer;
begin
   Result := GetDataRecord.YYYY;
end;

class function TBase.GetDataRecord: PDataRecord;
begin
   Result := PlainReadDataRecord;
   if nil <> Result then exit;

   New(Result);
   DataPointersToFree.Add( Result );
   PlainSaveDataRecord( Result );

  (*** заполнение полей Result^ по аттрибутам или еще как ****)
end;


class function TBase.PlainReadDataRecord: PDataRecord;
begin
   Result := ClassData;
end;

class procedure TBase.PlainSaveDataRecord( const ptr: PDataRecord );
begin
   ClassData := ptr;
end;

class constructor TBase.ClaCreate;
begin
   DataPointersToFree := TList.Create;
end;

class constructor TBase.ClaDestroy; var p: pointerl
begin
   if nil <> DataPointersToFree then begin
      for p in DataPointersToFree do 
         Dispose(p);
      DataPointersToFree.Destroy;
  end;
end;



Копи-паст и boilerplate сведётся к

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
TChild = class (TBase)
  protected 
   class var ClassDataChild: PDataRecord;
   class function PlainReadDataRecord: PDataRecord; override;
   class procedure PlainSaveDataRecord( const ptr: PDataRecord ); override;
.....

class function TChild.PlainReadDataRecord: PDataRecord;
begin
   Result := ClassDataChild;
end;

class procedure TChild.PlainSaveDataRecord( const ptr: PDataRecord );
begin
   ClassDataChild := ptr;
end;
...
Рейтинг: 0 / 0
14.08.2017, 14:04:28
    #39504963
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
классовые константы дочернего объекта
Arioch
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
class function TBase.PlainReadDataRecord: PDataRecord;
begin
   Result := ClassData;
end;

class procedure TBase.PlainSaveDataRecord( const ptr: PDataRecord );
begin
   ClassData := ptr;
end;



Кстати, в Base они скорее всего не нужны, можно сделать virtual abstract
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / классовые константы дочернего объекта / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]