Постоянный экземпляр класса - PullRequest
2 голосов
/ 21 декабря 2009

Если я определяю запись, я могу определить экземпляр этой записи как постоянная запись например,

Tunit = record
  _name: string;
  _scale: real;
end;

const metre: Tunit =
  (_name: 'metre';
   _scale: 1.0;
  )

Мне нужно сделать нечто подобное, когда Tunit является Class , а meter является экземпляром класса, но является (конкретным) экземпляром, связанные поля которого не могут быть изменены другим кодом. Я не вижу, как этого добиться. Есть идеи, пожалуйста?

Ответы [ 3 ]

4 голосов
/ 21 декабря 2009

попробуйте только для чтения свойства:

interface
type
  TUnit = class
  private
     _name: string;
     _scale: real;
     class function makeunit(aname: string; ascale: real): TUnit;
  public 
     property name: string read _name;
     property scale: real read _scale;
  end;

function metre: TUnit;

implementation

var
  _metre : TUnit = nil;

class function TUnit.makeunit(aname: string; ascale: real): Tunit;
begin
  Result._name := aname;
  Result._scale := ascale;
end;

function Metre: TUnit;
begin
  if not Assigned(_metre) then
    _metre := TUnit.makeunit('metre', 1.0);
  result := _metre;
end;

finalization
  FreeAndNIL(_metre);
4 голосов
/ 21 декабря 2009

Есть два способа достичь чего-то подобного , в зависимости от ваших потребностей:

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

а)

  interface

  var
    metre : TUnit = NIL;  // Can initialise a unit variable

   :

  implementation

   :

  initialization
    metre := TUnit.Create( ... );

  finalization
    FreeAndNIL(metre);

  end.

ПРИМЕЧАНИЕ. Если ваш класс является просто контейнером для данных, как это следует из вашего вопроса, то вы можете рассмотреть вопрос об исключении финализации Free'ing - хотя техническая утечка памяти, вы фактически ничего не потеряете, так как память используется вашей экземпляр будет восстановлен, когда ваш процесс приложения завершится. Бесплатное завершение может привести к проблемам, если другой код завершения в вашем проекте получит доступ к экземпляру счетчика после его освобождения.

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

б)

  interface

    function Metre: TUnit;

  implementation

  var
    _metre : TUnit = NIL;  // Can initialise a unit variable


  function Metre: TUnit;
  begin
    if NOT Assigned(_metre) then
      _metre := TUnit.Create( ... );

    result := _metre;
  end;


  finalization
    FreeAndNIL(metre);

  end.

Те же наблюдения с возможностью окончательного оформления применимы и в этом случае.

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

Второй способ добиться этого - использовать функции класса для возврата фиксированных значений из специально полученного класса, а не использовать данные-члены. Тогда вам вообще не нужно создавать экземпляр класса и не нужно беспокоиться о его утилизации. Я не могу вспомнить, если Delphi 2010 теперь поддерживает переменные класса, а также функции класса - если да, то это тоже может быть ответом. Но если вы не используете Delphi 2010, вопрос все равно будет спорным.

Это будет выглядеть примерно так:

TMetre = class(TUnit)
  class function Name: String; override;
  class function Scale: Double; override;
end;

и т.д.

Интересно, однако ... Вам известно о функциональности единицы стандартного преобразования и связанной с ней единиц измерения? Я спрашиваю только потому, что содержание этого вопроса выглядит так, как будто оно уже удовлетворено существующим аспектом Delphi RTL.

0 голосов
/ 22 декабря 2009

Хотя технически возможно создание постоянных значений объектов, эта концепция несовместима с обычными методами освобождения памяти, а Delphi / native не поддерживает ее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...