Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-07

Extending an enumeration

6 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Mark Morgan Lloyd

If I have a class with a property Phase: TrrPhase where TrrPhase is an enumeration such as (rrQuiescent, rrInitialised), is there an elegant way of extending the enumeration and overriding the property type so that a derived class can use the new values?

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Jetcheng Chu
to Mark Morgan Lloyd

As far as I know, properties cannot be overridden. However, you could consider using subrange types, as the example below shows.

type
  Fruit = (Apple, Banana, Cherry, Orange, Pineapple);
  LimitedFruit = Apple..Cherry;

You can use the full enumeration as the property's type, and then restrict its value using a custom property setter.

Earlier message 15 lines
------ Original Message ------ Subject: [fpc-pascal] Extending an enumeration Date: Sun, 18 Jul 2010 16:23:13 +0000 To: From: Mark Morgan Lloyd > If I have a class with a property Phase: TrrPhase where TrrPhase is an > enumeration such as (rrQuiescent, rrInitialised), is there an elegant > way of extending the enumeration and overriding the property type so > that a derived class can use the new values? > -- Jetcheng Chu http://people.rerouted.org/jcchu

Reply by email

Mark Morgan Lloyd
to Jetcheng Chu
Jetcheng Chu wrote 9 lines
As far as I know, properties cannot be overridden. However, you could consider using subrange types, as the example below shows. type Fruit = (Apple, Banana, Cherry, Orange, Pineapple); LimitedFruit = Apple..Cherry; You can use the full enumeration as the property's type, and then restrict its value using a custom property setter.

Yes, I was thinking that. However if the basic class was say a round-robin scheduler with phases rrQuiescent and rrInitialised and the descendant was say an HP comms protocol handler with additional phases hpReceivingPadding, hpReceivedSync and so on it would seem to be questionable practice to have to define all possible enumerated values in the basic class.

I suppose one possibility would be to define hpPhase= (hpQuiescent:= rrQuiescent, ... ) and to forcibly disable some of the runtime type checking, but it's hardly elegant.

Which suggests that the best way is probably to have separate properties controlling the phase of execution (i.e. whether the code is properly initialised) and the state of the protocol or whatever being implemented.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Jetcheng Chu
to Mark Morgan Lloyd
Show quoted text 6 lines
Yes, I was thinking that. However if the basic class was say a round-robin scheduler with phases rrQuiescent and rrInitialised and the descendant was say an HP comms protocol handler with additional phases hpReceivingPadding, hpReceivedSync and so on it would seem to be questionable practice to have to define all possible enumerated values in the basic class.

It seems to me that these states are mutually exclusive, and you won't be using the SET type thereof. An enumeration type in this case doesn't seem to offer any real benefit. Instead you could consider using separate constant definitions, which will also be (mostly) syntactically compatible with your existing code.

Reply by email

Thierry Coq
to Mark Morgan Lloyd: Yes, I was thinking that. However if the basic class was say a round-robin scheduler with…

On 18/07/2010 20:56, Mark Morgan Lloyd wrote:
...

Show quoted text 7 lines
Yes, I was thinking that. However if the basic class was say a round-robin scheduler with phases rrQuiescent and rrInitialised and the descendant was say an HP comms protocol handler with additional phases hpReceivingPadding, hpReceivedSync and so on it would seem to be questionable practice to have to define all possible enumerated values in the basic class.

...
In this case, enumeration cannot be extended. If you look at it from an analysis point of view, you're implementing a state machine with an enumeration. If your state machine is extendable instead of fixed, and you want to add substates to it, then a possible implementation is to define a state class:

TSchedulerPhase = Class(TObject);
where the basic phases are defined as variables in the base class, and
initialized in the initialization of the base module:
var
    spQuiescent: TSchedulerPhase;
    spInitialized: TSchedulerPhase;
Initialization
   spQuiescent := TSchedulerPhase.Create;
...

The descendent class can add other states, and compute other transitions. This is a classic implementation of the state design pattern.

I hope this helps,
Thierry.

Reply by email

Mark Morgan Lloyd
to Thierry Coq
Thierry Coq wrote 15 lines
On 18/07/2010 20:56, Mark Morgan Lloyd wrote: ... > Yes, I was thinking that. However if the basic class was say a > round-robin scheduler with phases rrQuiescent and rrInitialised and > the descendant was say an HP comms protocol handler with additional > phases hpReceivingPadding, hpReceivedSync and so on it would seem to > be questionable practice to have to define all possible enumerated > values in the basic class. > ... In this case, enumeration cannot be extended. If you look at it from an analysis point of view, you're implementing a state machine with an enumeration. If your state machine is extendable instead of fixed, and you want to add substates to it, then a possible implementation is to define a state class:

I agree, but that's more a poor choice of example on my part than an invalidation of the original question.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email