Enumerations
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Written against MATLAB R2026b. Enumeration classes have been part of the language since R2010b, when classdef files gained the enumeration block (the reference page of the enumeration function itself gives R2009b as its introduction), so everything below that does not carry a release number works in every release this section covers. The one newer detail is flagged where it appears: since R2026a, an enumeration derived from a numeric class cannot have sparse underlying values. The class files shown are checked line by line against the R2026b documentation. Octave 11.3.0 cannot parse an enumeration block at all, so none of the MATLAB sessions here were run; the Octave attempt is described in its own section and every output shown is quoted from the documentation, adapted where noted, and labelled "not run here".
An enumeration class defines a fixed set of named values of one type. Use one when a variable can take only a few well-known states and a free-form string or a magic number would invite typos: a traffic-light colour, a machine state, a day of the week. The heatflow scenario (The heatflow scenario) uses one for the kind of boundary condition applied to the plate edges: heatflow.BoundaryKind with the members Dirichlet, Neumann and Periodic. Classes in general are introduced on Classdef Basics, and the difference between value and handle classes, which matters for enumerations with properties, on Value and Handle Classes.
Defining an enumeration class
An enumeration class is an ordinary classdef file with an enumeration block. Each line in the block names one enumeration member. Several names can share a line, separated by commas or whitespace as in the documentation example.
classdef WeekDays
enumeration
Monday, Tuesday, Wednesday, Thursday, Friday
end
end
Save it as WeekDays.m in a folder on the search path. As with every class, the file name must match the class name. The enumeration keyword is only a keyword inside a classdef block, next to properties, methods and events. A member is referred to as ClassName.MemberName, and it is an instance of the class:
today = WeekDays.Tuesday
class(today)
The documentation shows this output for the two statements (not run here):
today =
WeekDays enumeration
Tuesday
ans =
'WeekDays'
Referring to members and arrays
Members can be assigned to variables, collected in arrays and substituted for the superclass. These are the rules from the "Refer to Enumerations" page:
-
Arrays. Build an enumeration array by concatenation (
[WeekDays.Tuesday,WeekDays.Friday]) or by indexed assignment (a(1) = WeekDays.Tuesday). -
Default member. The default member is the first one listed in the
enumerationblock, hereWeekDays.Monday. When you assign to an element beyond the end of an array, the gap is filled with the default member. Aftera(5) = WeekDays.Tuesdayon a new variable, elements 1 to 4 areMonday. -
Text to member. Calling the class name like a function converts text to members:
WeekDays('Tuesday'),WeekDays(["Monday" "Friday"])orWeekDays({'Monday','Wednesday','Friday'}). Every text must name an existing member, otherwise the conversion fails. -
Text coerced to member. A user-defined class dominates
char, soa(end+1) = 'Tuesday'appends the memberWeekDays.Tuesdayto an existing arrayaof members. Concatenating[WeekDays.Wednesday,'Friday']also gives aWeekDaysarray. -
Member to text. Functions that expect a character vector accept a member because it converts automatically:
sprintf('Today is %s',WeekDays.Friday)returnsToday is Friday.
wd = WeekDays({'Monday','Wednesday','Friday'});
wd(end+1) = 'Tuesday'; % the char vector is coerced to WeekDays.Tuesday
msg = sprintf('Today is %s',WeekDays.Friday);
The code above is the documentation’s pattern assembled from its separate examples, not run here.
Enumerations derived from built-in types
An enumeration class can name a superclass, and each member then carries a value of that type, given in parentheses after the member name. The default constructor passes the value to the superclass constructor.
classdef Bearing < uint32
enumeration
North (0)
East (90)
South (180)
West (270)
end
end
b = uint32(Bearing.East) returns the uint32 value 90, because the uint32 constructor accepts an instance of the subclass. The documentation says other superclasses can reject that conversion unless their constructor accepts the enumeration class. Since R2026a, enumerations derived from numeric superclasses cannot have sparse underlying values.
An enumeration member can be used where the superclass is expected, and the result has the superclass type. The documentation’s PPM < double class has members High (1000), Medium (100) and Low (10); PPM.High + 100 gives the double 1100. The reverse also works in a switch: with case PPM.Low, case PPM.Medium and case PPM.High, calling the function with the plain number 100 selects Medium.
A class derived from logical gives a readable boolean:
classdef Bool < logical
enumeration
No (0)
Yes (1)
end
end
If the class has several superclasses, MATLAB passes the member’s arguments to the first superclass constructor only, and calls the constructors of the others with no arguments. The page describes the default constructor as behaving like obj@logical(val) followed by obj@MyBool for Bool < logical & MyBool. A built-in-derived enumeration can also give one member more than one name; the enumeration function then shows only the first unless you request both outputs (see below).
Methods and properties in an enumeration
An enumeration class can have ordinary methods blocks. A method sees its member as the first argument.
classdef WeekDays
enumeration
Monday, Tuesday, Wednesday, Thursday, Friday
end
methods
function tf = isMeetingDay(obj)
tf = WeekDays.Tuesday == obj;
end
end
end
WeekDays.Tuesday.isMeetingDay and isMeetingDay(WeekDays.Wednesday) return 1 and 0, in the documentation’s session.
Add properties when each member carries data. Set them in the constructor, whose argument list is the one written after each member name:
classdef SyntaxColors
properties
R
G
B
end
methods
function c = SyntaxColors(r,g,b)
c.R = r; c.G = g; c.B = b;
end
end
enumeration
Error (1,0,0)
Comment (0,1,0)
Keyword (0,0,1)
String (1,0,1)
end
end
SyntaxColors.Error.R is 1. The constructor runs when the member is first referenced, and the class is a value class, so afterwards only the constructor can set the properties: e.R = 0 fails with the documented message "You cannot set the read-only property 'R' of SyntaxColors." Value-based enumeration classes implicitly make every property’s SetAccess immutable and do not let you choose another value; superclass properties must also be declared with immutable SetAccess.
Value enumerations versus handle enumerations
The choice follows the rule for any class (see Value and Handle Classes): use a value enumeration for a fixed set of immutable values, and a handle enumeration, one that derives from handle, only when the state attached to a member must change.
| Aspect | Value enumeration | Handle enumeration |
|---|---|---|
Properties |
Immutable; set only in the constructor. |
Mutable. |
Identity |
|
Only one instance of each member exists in a session, so two references are the same handle ( |
Changing a property |
Not allowed. |
Changes the member for every reference, including ones created later, until |
Copying |
Not applicable. |
You cannot derive from |
The documentation demonstrates the handle case with a HandleColors < handle class: after a.R = 0.8, a new reference HandleColors.Red reports R as 0.8, clear of the variables does not undo it, and clear classes does. Prefer value enumerations. A mutable "constant" that survives clear is a hidden global variable (see Workspaces, Scope, Global and Persistent Variables).
A common use is to store a state in a handle object that is not itself an enumeration:
classdef MachineState
enumeration
Running
NotRunning
end
end
classdef Machine < handle
properties (SetAccess = private)
State = MachineState.NotRunning
end
methods
function start(machine)
if machine.State == MachineState.NotRunning
machine.State = MachineState.Running;
end
disp(machine.State.char)
end
function stop(machine)
if machine.State == MachineState.Running
machine.State = MachineState.NotRunning;
end
disp(machine.State.char)
end
end
end
Following the documentation, m = Machine; m.start prints Running and m.stop prints NotRunning (not run here). The == and char methods keep the code readable.
Operations on enumerations
Every enumeration class has default methods for comparing and converting members. The documentation lists them for WeekDays with methods('WeekDays'): the constructor WeekDays, char, cellstr, string, eq, ne, ismember, intersect, setdiff, setxor, union, strcmp, strcmpi, strncmp and strncmpi.
| Operation | Behaviour |
|---|---|
|
Convert a member or array to a string, a character vector, or a cell array of character vectors, for building messages. |
|
Compare members with text. Against one text value, an array of members returns a logical array of the same size. |
|
Also compares members with text, but requires equal sizes, so |
|
Compares a member with text. One argument must be text: comparing two members returns false. |
|
Set membership. Text mixed with members is converted to the enumeration class first, so |
|
Set operations on enumeration arrays. |
switch and if
Because eq is defined, members work directly in switch and if:
function c = reminder(day)
switch day
case WeekDays.Monday
c = 'No meetings';
case WeekDays.Tuesday
c = 'Department meeting at 10:00';
case {WeekDays.Wednesday, WeekDays.Friday}
c = 'Team meeting at 2:00';
case WeekDays.Thursday
c = 'Volleyball night';
otherwise
error('Unsupported day.');
end
end
The documentation version omits the otherwise branch, with the comment "Add error checking here"; without it, a member not listed leaves c unassigned and the caller fails later. The output Team meeting at 2:00 for reminder(WeekDays.Wednesday) is the documented one (not run here). The page also shows a variant that switches on text with case 'Monday', and says to avoid it when you do not need text, because MATLAB must convert the text to a member on every comparison.
Listing the members
enumeration WeekDays prints the member names, and the function form returns them:
m = enumeration('WeekDays'); % column vector of members
[m,s] = enumeration('WeekDays'); % s is a cell array of names
Here enumeration(obj) takes an instance instead of a class name, and the reference page shows matlab.lang.OnOffSwitchState (members off and on) as the example. enumeration is the usual way to loop over every member.
The heatflow boundary kind
In the heatflow project the boundary condition is a closed set with three names, which is what an enumeration is for. It lives in the namespace folder +heatflow (see Namespaces and Class Folders), so the file is +heatflow/BoundaryKind.m:
classdef BoundaryKind
% BoundaryKind Condition applied at the edges of the plate.
enumeration
Dirichlet % edge temperature held at a fixed value
Neumann % no heat flows through the edge
Periodic % opposite edges are connected
end
end
Dirichlet is first, so it is the default member: assigning x(3) = heatflow.BoundaryKind.Periodic to a new variable fills x(1:2) with Dirichlet. Code that uses the kind selects the behaviour with a switch and rejects anything else. This helper updates the edge rows and columns of a temperature matrix T, where the first and last rows and columns are boundary cells and the interior starts at index 2:
function T = applyBoundary(T,kind,edgeValue)
%applyBoundary Set the edge cells of T for a heatflow.BoundaryKind.
arguments
T (:,:) double
kind (1,1) heatflow.BoundaryKind
edgeValue (1,1) double = 20
end
switch kind
case heatflow.BoundaryKind.Dirichlet
T([1 end],:) = edgeValue;
T(:,[1 end]) = edgeValue;
case heatflow.BoundaryKind.Neumann
T([1 end],:) = T([2 end-1],:);
T(:,[1 end]) = T(:,[2 end-1]);
case heatflow.BoundaryKind.Periodic
T(1,:) = T(end-1,:);
T(end,:) = T(2,:);
T(:,1) = T(:,end-1);
T(:,end) = T(:,2);
otherwise
error('heatflow:unknownBoundary','Unsupported boundary kind.');
end
end
The arguments block (see Argument Validation) converts a character vector such as 'Neumann' into the member for you, because an enumeration class converts text that names a member. This is the same conversion described under "Referring to members" above. The otherwise branch can only be reached if a member is added to the enumeration and the switch is not updated, which is exactly the situation it is there to catch. The code is the project’s own illustration, written from the documented switch and indexing rules and not run here. The Simulation class stores the choice in its Boundary property, typed heatflow.BoundaryKind, so assigning anything that is not a member or convertible text fails at assignment (see Properties and Methods).
The diagram is original and shows only the relationship used here.
Pitfalls
-
Typos in text.
WeekDays('Tuesdy')andx = WeekDays.Sundayboth fail because the name is not a member. The error wording varies by release (not run here), so test for the condition, not the message. -
Text comparisons are not case-folded.
m == "friday"is false when the member isFriday; usestrcmpifor case-insensitive comparison. -
Two members never match under
strcmp. One argument must be text. -
isequaland sizes. An array compared with a single text value is not equal; use==andallorany. -
Gaps in arrays take the default member, not an empty value. Reserve the first name for a safe default.
-
Handle enumerations survive
clear. A changed property stays untilclear classes. -
Adding a member later changes the default only if it is placed first, and any
switchover the class needs a newcase. -
Do not reorder members in a numeric-derived enumeration without checking the values: the value, not the position, is what the superclass sees.
Octave and enumerations
Octave 11.3.0 does not implement the enumeration block. A class file with this body, saved as BoundaryKind.m, was run with a short script that referenced BoundaryKind.Neumann in a try block:
classdef BoundaryKind
enumeration
Dirichlet
Neumann
Periodic
end
end
Octave 11.3.0 output (the MATLAB wording of errors differs):
syntax error near line 4, column 0 in file /work/BoundaryKind.m
The error is raised when the class file is parsed, so the try block cannot catch it. A portable program that must run in both systems has to represent the choice another way, for example with a validated text value (any(strcmp(kind,{'Dirichlet','Neumann','Periodic'}))). Everything else on this page needs MATLAB.
Where the books are outdated
Older MATLAB books either do not mention enumerations or stop at a numeric flag (isFixed = 1) or a character vector compared with strcmp, since they were written before enumeration classes were common practice or before the arguments block could validate a property’s class. Both patterns still run. The enumeration class gives them a type: the assignment is checked, the names can be completed in the editor, and a switch reads as the specification. A book that says a switch or if cannot compare objects is describing code written before eq was defined for enumerations, and one that treats classes as "packages" is using the pre-R2024a name for a namespace (see Namespaces and Class Folders). The remark that numeric-derived enumerations cannot be sparse (R2026a) appears in no book.