Конференция "Основная" » Дополнение перечисления
 
  • Kolan © (16.03.09 11:32) [0]
    Здравствуйте!

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

    Примерно так:

    base.pas

    TCommandTypes =
     (
       mtDeviceError = $FF,
       mtVersionInfoRequest = $00,
       mtVersionInfoAnswer = $80,  
     );




    special.pas

    TCommandTypes =
     (
       mtOperationModeRequest = $01,
       mtOperationModeAnswer = $81,
       mtImpedanceMeasurmentStartRequest = $02,
       mtMeasurmentStartAnswer = $82,
    ...
     );



    Такое дополнение перечислений хочется сделать для того, что бы в базовом модуле создать набор функций, которые бы принимали
    TCommandTypes

    и работали бы как для команд из базового модуля, так и для команд из любого другого и вместе с тем работала бы проверка времени компиляции.

    Понятно, что если я поступлю так как в примере, то базовый набор команд будет просто закрыт и ничего не получится.

    Как можно добиться желаемого?
  • Медвежонок Пятачок © (16.03.09 11:36) [1]
    одно полное длинное перечисление.
    там, где хочется контроль по ограниченному перечню - ассерт
  • Palladin © (16.03.09 11:52) [2]

    > Kolan ©   (16.03.09 11:32) 

    Чем простые константы не устроили?
  • MsGuns © (16.03.09 11:58) [3]
    Интересно, откуда возникло такое желание, ведь суть перечислений - это именно постоянность
  • Kolan © (16.03.09 12:40) [4]
    >Чем простые константы не устроили?

    Из всех вариантов этот мне нравится больше всего, но плохо, что в методах придется писать
    Foo(Command: Integer)

    , а не
    Foo(Command: TCommandTypes)

    .

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

    >одно полное длинное перечисление.
    Это невозможно сделать, я не знаю какие команды будут у устройств, которые появятся, скажем, в следующем году.
  • Palladin © (16.03.09 12:50) [5]

    > Kolan ©   (16.03.09 12:40) [4]

    И в чем проблемы?

    Type
    TCommandType=type Integer;

    Const
    mtDeviceError:TCommandType = $FF

  • Медвежонок Пятачок © (16.03.09 12:54) [6]
    Это невозможно сделать, я не знаю какие команды будут у устройств, которые появятся, скажем, в следующем году.

    Тогда стоит подумать вообще о логичности выбора перечисления как нудного типа.
    Хотя не вижу препятствий.
    У меня тодже команды и тоже перечисления, причем даже без уточнения значений. Перечень команд постоянно из месяца в месяц растет.
    И ничему этот рост не мешает.
  • Kolan © (16.03.09 12:59) [7]
    Palladin, отлично! Проверки типа нет, но подсказка при вызове функции выводится вполне понятная. Я думаю путаницы не возникнет, поэтому считаю, что ответ получил — благодарю.
  • Ega23 © (16.03.09 13:08) [8]

    > Проверки типа нет,


    ЕМНИП, когда type Integer - проверка есть. Хотя тут уже могу ошибаться.
  • Kolan © (16.03.09 13:38) [9]
    Ega, я проверил:

     TForm2 = class(TForm)
    ...
     public
       { Public declarations }
       procedure foo(command: TCommandType);
     end;

    procedure TForm2.foo(command: TCommandType);
    begin
     ShowMessage(IntToStr(command));
    end;

    procedure TForm2.FormCreate(Sender: TObject);
    begin
     foo(1);
    end;



    Единичку показал. Так что проверки нет. Но я думаю, что правильный префикс и подсказка при вызове метода поможет избежать проблем.
  • Dimka Maslov © (16.03.09 13:43) [10]
    Проверка производится только когда переменная передаётся в функцию через var. В этом случае integer и type integer трактуются как разные типы.
  • Kolan © (16.03.09 13:50) [11]
    Возникла проблема в операторе case.

    Если объявлять константы так:

    type
     TCommandType = type Integer;
    const

     ctDeviceError: TCommandType = $FF;
    ...



    И использовать так:

    function TCustomFreGrafDeviceProtocol.DefineCommandType(
     Command: TCommandType): string;
    begin
     case Command of
       ctDeviceError:
         Result := rsDeviceError;
    ...



    То компилятор говорит, что:
    Constant expression expected

    в строке с
    ctDeviceError:

    . Если убрать из объявления констант
    TCommandType

    , то есть написать просто
    ctDeviceError = $FF;

    , то скомпилировать удается. Но в этом случае получается, что константы не связаны с типом TCommandType.

    Как объяснить компилятору, что это константа?
  • Медвежонок Пятачок © (16.03.09 14:08) [12]
    зачем все это?
    иметь перечисление TEnum = (one,two,three)
    и массив array[TEnum] (и то если важно десятичное значение).

    и все.

    Для алгоритма значение не нужно, ну а девайс посылать прямо значения енума - не очень логично.
  • Kolan © (16.03.09 14:37) [13]
    Медвежонок Пятачок, я не понимаю что вы предлагаете.

    Попробую объяснить еще раз.
    Мне хочется написать метод
    Foo(Command: TCommandType);

    . Command — это некоторое число которому надо дать осмысленное имя.

    Проблема в том, что с одной стороны в одном модуле число
    $90

    может означать одно, а в другом другое и программист должен видеть и понимать что от него хотят и что он передал, а с другой
    Foo

    должно работать с любым переданным числом.

    Причем тут массив — не ясно.

    >...ну а девайс посылать прямо значения енума - не очень логично.
    Почему не логично? Я думаю, что запись
    SendCommand(1);

    гораздо хуже чем запись  
    SendCommand(ctBlowUp);

    . Вы так не считаете?
  • Медвежонок Пятачок © (16.03.09 14:57) [14]
    Причем тут массив — не ясно.

    TEnum = (one,two,three)

    все ясно и понятно. элементы перечисления с осмысленными именами.
    и кейс доволен.
  • Kolan © (16.03.09 15:40) [15]
    Медвежонок Пятачок, как теперь в другом модуле добавить в TEnum еще four и five?
  • Медвежонок Пятачок © (16.03.09 16:32) [16]
    если в другом модуле, то это будет уже другой тип
  • Kolan © (16.03.09 16:37) [17]
    Тогда мне придется писать несколько функций для обработки этих констант, а это плохое решение.
  • Медвежонок Пятачок © (16.03.09 16:39) [18]
    я честно говоря не понимаю, почему расширение базового перечисления может чем-то помешать базовому модулю.
  • Германн © (16.03.09 17:00) [19]

    > Как объяснить компилятору, что это константа?
    >

    Это "типизированная" константа. А её значение можно изменить в рантайме. И как тут быть компилятору?
  • Kolan © (17.03.09 10:33) [20]
    Герман, если спросить меня, то я бы не делал констант, которые могут изменяться :).
    Пока просто убрал тип, и сделал документацию, но лучше бы код сам себя документировал.

    Медвежонок Пятачок, потому что метод в базовом модуле, который принимает тип TCommandType из этого же базового модуля не сможет принять тип TCommandType из другого модуля, так как это разные типы.
  • Медвежонок Пятачок © (17.03.09 17:58) [21]
    Вот поэтому я и не предлагал и не предлагаю "расширять" перечисление в других модулях.
    Одно перечисление на все про все.
    Растущее и удлинняющееся от версии к версии программы.
  • Германн © (18.03.09 00:07) [22]

    > Kolan ©   (17.03.09 10:33) [20]
    >
    > Герман, если спросить меня, то я бы не делал констант, которые
    > могут изменяться :).

    Это было введено в Паскаль очень давно. И поменьше, но тоже давно, объявлено Борландом как оставленное для обратной совместимости, и что в новых проектах использование типизированных констант не рекомендуется!
    Так что сам виноват, очкарик, что вляпался. :)
  • SPeller © (18.03.09 07:34) [23]

    > как теперь в другом модуле добавить в TEnum еще four и five?

    Очень просто. Руками. Берешь и добавляешь. В старом модуле ничего не поломается если там нет массивов на основе твоего старого перечисления (array[TEnum]) и все твои if и case предусматривают возможность появления значения вне рамок перечисления, определенных на этапе компиляции.
  • SPeller © (18.03.09 07:36) [24]
    Это если понятие "модуль" равно понятию "длл".
  • SPeller © (18.03.09 07:37) [25]
    А если всё внутри одного проекта, то, имхо, только константы с префиксами. Если неохота юзать переменные константы.
  • Kolan © (19.03.09 10:12) [26]

    > Это если понятие "модуль" равно понятию "длл".

    Понятие модуль равно понятию модуля (unit).


    > Растущее и удлинняющееся от версии к версии программы.

    Так нет версий программы. Это библиотечный модуль, который используют много кто.


    > А если всё внутри одного проекта, то, имхо, только константы
    > с префиксами.

    Так и поступил.


    > Так что сам виноват, очкарик, что вляпался. :)

    Давненько я тут не был. :)

    Вопрос считаю закрытым, благодарю за обсуждение.
  • Медвежонок Пятачок © (19.03.09 10:51) [27]
    Так нет версий программы. Это библиотечный модуль, который используют много кто.

    Пусть используют.
    С одним длинным перечислением.
    если у разработчиков нет массивов по перечислению, они и не заметят изменений типа перечисления.
 
Конференция "Основная" » Дополнение перечисления
Есть новые Нет новых   [118478   +40][b:0][p:0.002]