Действительно ли Delphi обрабатывает динамические классы лучше, чем статические?


Мне не раз говорили, что Delphi обрабатывает динамические классы лучше, чем статические.Таким образом, используя следующее:

type Tsomeclass=class(TObject)
  private procedure proc1;
  public 
    someint:integer;
    procedure proc2;
end;

var someclass:TSomeclass;

implementation

...

initialization
  someclass:=TSomeclass.Create;
finalization
  someclass.Free;

Вместо

type Tsomeclass=class
  private class procedure proc1;
  public 
    class var someint:integer;
    class procedure proc2;
end;

90% классов в проекте, над которым я работаю, имеют и нуждаются только в одном instance.Do я действительно должен использовать первый способ для использования этих классов? Он лучше оптимизирован, обрабатывается Delphi?

Извините,у меня нет аргументов, подтверждающих эту гипотезу, но мне нужно мнение эксперта.

Заранее спасибо!

2 2

2 ответа:

Если вы создаете класс, содержащий только переменные класса и методы класса, то вы можете использовать его без создания экземпляра. То есть во втором примере Вы можете использовать Tsomeclass.proc2 (но не Tsomeclass.некоторые, потому что эта переменная не была отмечена префиксом 'class', как указывал Уве).

Для (несомненно малой) разницы в скорости вы также можете пометить методы вашего класса как "статические".

type
  TSomeclass = class
    class procedure proc2; static;
  end;

На мой взгляд, здесь нет сравнения "лучше справляться". Дельфи позволяет вам чтобы поместить в класс "нормальных" и "классовых" членов. Первый вы можете использовать только на экземпляре объекта, а второй вы можете использовать в любом месте. Но это всего лишь две части поддержки OO в Delphi.

Правка: чтобы ответить на вопрос о скорости ...

Давайте составим небольшую тестовую программу:

program Project61;

{$APPTYPE CONSOLE}

type
  TTestClass = class
    procedure A(a: integer);
    class procedure B(b: integer);
    class procedure C(c: integer); static;
  end;

procedure TTestClass.A(a: integer); begin end;
class procedure TTestClass.B(b: integer); begin end;
class procedure TTestClass.C(c: integer); begin end;

var
  tc: TTestClass;

begin
  tc := TTestClass.Create;
  tc.A(42);
  tc.B(42);
  tc.C(42);
  tc.Free;
  //TTestClass.A(42); // not possible
  TTestClass.B(42);
  TTestClass.C(42);
end.

Delphi 2010 с включенной оптимизацией компилирует .Ля/.Б/.C вызывает в

Project61.dpr.30: tc := TTestClass.Create;
004060C5 B201             mov dl,$01
004060C7 A154594000       mov eax,[$00405954]
004060CC E847DAFFFF       call TObject.Create
004060D1 8BD8             mov ebx,eax
Project61.dpr.31: tc.A(42);
004060D3 BA2A000000       mov edx,$0000002a
004060D8 8BC3             mov eax,ebx
004060DA E899F9FFFF       call TTestClass.A
Project61.dpr.32: tc.B(42);
004060DF BA2A000000       mov edx,$0000002a
004060E4 8B03             mov eax,[ebx]
004060E6 E891F9FFFF       call TTestClass.B
Project61.dpr.33: tc.C(42);
004060EB B82A000000       mov eax,$0000002a
004060F0 E88BF9FFFF       call TTestClass.C
Project61.dpr.34: tc.Free;
004060F5 8BC3             mov eax,ebx
004060F7 E84CDAFFFF       call TObject.Free
Project61.dpr.36: TTestClass.B(42);
004060FC BA2A000000       mov edx,$0000002a
00406101 A154594000       mov eax,[$00405954]
00406106 E871F9FFFF       call TTestClass.B
Project61.dpr.37: TTestClass.C(42);
0040610B B82A000000       mov eax,$0000002a
00406110 E86BF9FFFF       call TTestClass.C

Объект создается первым,и его адрес сохраняется в регистре ebx.

К позвони ТК.A, компилятор подготавливает параметр (42 или $2A) в edx, адрес экземпляра 'tc' в eax и вызывает TTestClass.A.

Почти то же самое происходит и в ТК.Случай B за исключением того, что ebx разыменован.

В.А и .В случае B, eax содержит значение 'Self' (эквивалентно C++ ' s 'this'). Когда ТК.Вызывается A, eax содержит адрес экземпляра 'tc'. Когда ТК.B называется, eax содержит что-то еще (я предполагаю, что он указывает на информацию о типе для TTestClass, но я не совсем уверен в этом).

Когда код вызывает tc.C, только eax подготовлен, потому что "статические" методы не могут ссылаться на "себя".

Аналогичная ситуация возникает в классе Ttest.Б/.C случаи, за исключением того, что " я " загружается из некоторого постоянного местоположения, когда ??адрес TTestClass typeinfo?? сохраненный. В любом случае, eax содержит то же самое значение, когда B вызывается через экземпляр (tc.B) или через класс (TTestClass.Б).

Таким образом, вы можете видеть, что статические вызовы требуют на один 'mov' меньше. Это было то неизмеримое ускорение, о котором я говорил.

Вы говорите, один экземпляр или нет экземпляров?

В вашем втором примере вы не можете создать экземпляр этого.

Я еще не видел, чтобы кто-то использовал статические классы в производственном коде. Вы все еще можете объявить статические методы (класс) в своем первом примере.

Используйте обычный типизированный класс, но объявите class var, class procedure, и class function(). Вы можете вызывать методы класса и ссылаться на переменные класса без создания экземпляра.

Вот так:

type
  TSomeClass = class(TObject)
    class var
      somevar: String;
    class procedure Hello;
  end;

Обратите внимание, что переменные класса были добавлено где-то после Delphi 7, но вы определенно должны уметь делать методы класса.