powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / классовые константы дочернего объекта
16 сообщений из 16, страница 1 из 1
классовые константы дочернего объекта
    #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
классовые константы дочернего объекта
    #39503696
alekcvp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arshehremen,
Я когда-то пытался так делать, не работает. В каком классе метод - из того класса и константа будет.
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #39503713
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
используй классовую переменную, а константу в нее грузи из классового конструктора
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #39503730
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Константы не являются виртуальными. В дочерних классах появляется свой экземпляр SValue, про который базовый класс и его виртуальный метод не знают ничего.
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #39503776
Pu4koff
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вроде бы начиная с 2010 версии появились атрибуты. Можно через них сделать.
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #39503927
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Pu4koff,

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

....жаль, что классовые конструкторы не виртуальны...
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #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
классовые константы дочернего объекта
    #39504084
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сделай ридонли свойство вместо константы.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #39504118
Гаджимурадов Рустам
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящий> сделай ридонли свойство вместо константы.

А толку-то? Заполнять-то его всё равно где-то
надо, в конструкторе, методе или ещё где.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #39504127
Vizit0r
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch....жаль, что классовые конструкторы не виртуальны...
зато из конструктора запросто вызывается виртуальный метод. Проблема-то в чем?
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #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
классовые константы дочернего объекта
    #39504530
schi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
классовые константы дочернего объекта
    #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
классовые константы дочернего объекта
    #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
классовые константы дочернего объекта
    #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
классовые константы дочернего объекта
    #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
16 сообщений из 16, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / классовые константы дочернего объекта
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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