Как собрать в группу постоянные строки в Delphi

Даже я столкнулся с подобной ошибкой при запуске json.dump (). В моем случае я получал строку ошибки:

AttributeError: у объекта 'file' нет атрибута 'dump'

Как я это исправил -

Я использовал имя переменной как "JSON" для дескриптора файла в том же сценарии, поэтому я получил эту ошибку. Поэтому я просто переименовал имя переменной и проблема разрешилась.

11
задан Re0sless 29 May 2009 в 16:13
поделиться

7 ответов

Как упоминал Джим, вы можете использовать константы класса или перечислимый тип:

type
  TItemStatus = (isOpen, isActive, isClosed);
const
  ItemStatusStrings: array[TItemStatus] of string = ('Open', 'Active', 'Closed');
13
ответ дан 3 December 2019 в 01:16
поделиться

См. http: //edn.embarcadero.com/article/34324 («Новые возможности языка Delphi начиная с Delphi 7».

Подойдет константа класса. Из приведенной выше ссылки:

type
    TClassWithConstant = class
      public 
        const SomeConst = 'This is a class constant';
    end;


 procedure TForm1.FormCreate(Sender: TObject);
 begin
   ShowMessage(TClassWithConstant.SomeConst);
 end;
12
ответ дан 3 December 2019 в 01:16
поделиться

Или вы можете объединить @ Jim и @ TOndrej

TGlobalConsts = class
type
  TItemStatus = (isOpen, isActive, isClosed);
const
  ItemStatusStrings: array[TItemStatus] of string = ('Open', 'Active', 'Closed');
end;

Хотя вы могли бы сделать его классом или записью на самом деле. Хотя, если это класс , вы можете добавить функции класса , например, @ mghie , и вместо этого просто получить значения из массива const ]. Лично я предпочитаю иметь все строки в массиве констант в интерфейсе вместо того, чтобы засыпать их в телах функций в реализации . 1290] Есть много способов сделать это, это точно.

4
ответ дан 3 December 2019 в 01:16
поделиться

Я лично широко использовал подход TOndrej на нескольких крупных платформах обработки критически важных данных. Преимущество перечислений в том, что их можно легко передавать в приложении, они очень компактны (порядковый тип), отлично работают с операторами case и полностью безопасны по типу. Последний момент важен для обслуживания, так как удаление или изменение значений перечисления вызовет ошибку компиляции (хороший вариант, ИМХО).

Некоторые проблемы, на которые следует обратить внимание при этом подходе:

  • Изменение объявленного порядка значений перечисления приведет к ошибкам запретить поисковый массив enum-> string.

  • Если вы используете операторы enum in case (хорошая функция), обязательно учитывайте добавляемые новые значения. Обычно я добавляю else к случаю и создаю исключение для неизвестных значений. Гораздо лучше, чем провалиться.

Если вас очень беспокоит первая проблема, вы можете использовать запись в поисковом массиве и включить значение перечисления в каждую запись и проверить порядок при инициализации модуля. Это много раз спасало мой бекон в критически важных системах, где требуется частое обслуживание. Этот подход также можно использовать для добавления дополнительных метаданных к каждому значению (очень удобная функция).

Удачи!

unit Unit1;

interface

type
  TItemStatusEnum = (isOpen, isActive, isClosed);

  TItemStatusConst = class
    class function EnumToString(EnumValue : TItemStatusEnum): string;
    property OPEN: string index isOpen read EnumToString;
    property CLOSED: string index isClosed read EnumToString;
    property ACTIVE: string index isActive read EnumToString;
  end;

var
  ItemStatusConst : TItemStatusConst;

implementation

uses
  SysUtils;

type
  TItemStatusRec = record
    Enum  : TItemStatusEnum;
    Value : string;
  end;

const
  ITEM_STATUS_LOOKUP : array[TItemStatusEnum] of TItemStatusRec =
    ((Enum: isOpen;   Value: 'OPEN'),
     (Enum: isActive; Value: 'ACTIVE'),
     (Enum: isClosed; Value: 'CLOSED'));

procedure ValidateStatusLookupOrder;
  var
    Status : TItemStatusEnum;
  begin
    for Status := low(Status) to high(Status) do
      if (ITEM_STATUS_LOOKUP[Status].Enum <> Status) then
        raise Exception.Create('ITEM_STATUS_LOOKUP values out of order!');
  end;

class function TItemStatusConst.EnumToString(EnumValue: TItemStatusEnum): string;
  begin
    Result := ITEM_STATUS_LOOKUP[EnumValue].Value;
  end;

initialization
  ValidateStatusLookupOrder;
end.

Обновление:

Спасибо за критику - вы абсолютно правы в том, что я решал что я воспринимал как проблему, лежащую в основе вопроса. Ниже приводится гораздо более простой подход, если вы можете жить с ограничением, что он должен работать ТОЛЬКО в Delphi 2007 или более поздних версиях (может работать в D2006?). Трудно избавиться от назойливых мыслей об обратной совместимости;)

type
  ItemStatusConst = record
    const OPEN   = 'OPEN';
    const ACTIVE = 'ACTIVE';
    const CLOSED = 'CLOSED';
  end;

Этот подход прост и похож на то, что можно сделать в приложении Java или .Net. Семантика использования соответствует ожиданиям и будет работать с автозавершением кода. Большим плюсом является то, что константы имеют область видимости на уровне записи, поэтому нет риска конфликтов с другими определениями, как это происходит с типами с единичной областью видимости.

Sample usage:

    ShowMessage(ItemStatusConst.ACTIVE);
    ShowMessage(ItemStatusConst.CLOSED);

Ради забавы, я также пересмотрел свой предыдущий подход, чтобы напрямую ответить на исходный вопрос. с аналогичным исходом. На этот раз я использовал «смоделированные свойства класса» (см. здесь ) с индексатором свойств. Это явно более сложный, чем рекордный подход, но сохраняет возможность работы со значениями перечисления, наборами, строками И также может быть расширен для реализации дополнительных функций метаданных, где это необходимо. Я считаю, что это работает для версий Delphi, начиная с Delphi 5 IIRC.

Примером того, где я использовал этот метод с большим эффектом, была структура синтаксического анализа, которую я создал в Delphi для обработки полной IBM AFPDS печатает грамматику потока данных. Благодаря этой гибкости я люблю работать в Delphi - это как швейцарский армейский нож;)

Примером того, где я использовал эту технику с большим эффектом, был фреймворк синтаксического анализа, который я создал в Delphi для обработки полной грамматики потока данных печати IBM AFPDS . Благодаря этой гибкости я люблю работать в Delphi - это как швейцарский армейский нож;)

Примером того, где я использовал эту технику с большим эффектом, был фреймворк синтаксического анализа, который я создал в Delphi для обработки полной грамматики потока данных печати IBM AFPDS . Благодаря этой гибкости я люблю работать в Delphi - это как швейцарский армейский нож;)

8
ответ дан 3 December 2019 в 01:16
поделиться

Это то, что вы можете делать во всех версиях Delphi:

type
  TStatus = class
    class function Active: string;
    class function Open: string;
    ...
  end;

  class function TStatus.Active: string;
  begin
    Result := 'ACTIVE';
  end;

  class function TStatus.Open: string;
  begin
    Result := 'OPEN';
  end;

Вы можете использовать это именно так, как хотите:

MyVar := TStatus.Open;

есть ровно одно место для изменения строк, и там задействован только код, без создания экземпляра во время выполнения. Новые возможности последних версий Delphi не всегда необходимы для подобных вещей ...

3
ответ дан 3 December 2019 в 01:16
поделиться

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

Вы можете заполнить запись в разделе Initialize любого модуля, вызвав процедуру или функцию, объявленную в этом модуле. У вас может быть одно устройство, специально предназначенное для этой работы, например StatusTypes.pas.

В разделе интерфейса вы можете объявить что-то вроде:

type 
  TStatus = record
    OPEN: string;
  end;

var
  Status: TStatus;
1
ответ дан 3 December 2019 в 01:16
поделиться

В дополнение к тому, что сказал TOndrej:

Можно также объявить константу записи:

type
  TRecordName = record
    Field1: Integer;
    Field2: String
  end;

const
  itemstatus : TRecordName = (
    Field1: 0;
    Field2: 'valueoffield2'
  );

Также возможен массив записей путем объединения записи const синтаксис выше и синтаксис массива, показанный TOndrej.

Однако способ, который я обычно предпочитаю, требует инициализации:

  • заполнение TStringDynArray именами перечисления через RTTI
  • . Из-за того, что имена должны быть настраиваемыми, постоянство (как бы оно ни было организовано) может просто загружать / сохранять динамический массив.
2
ответ дан 3 December 2019 в 01:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: