Classes are useful when several values belong to the same job, dialog, tool change, probe cycle, or file operation.
A class is the definition. Calling the class creates an object. For practical script writing, you can think of it like this: define a class, then create one or more objects from it. Each object keeps its own data.
Instead of spreading related values across many separate variables, put them in one class object. This makes the script easier to read, easier to pass to functions, and easier to remove or replace when the job is finished.
A script can quickly collect many related variables:
safe_z = 5; probe_feed = 100; probe_depth = -2; probe_count = 0; probe_last_x = none(); probe_last_y = none(); probe_last_z = none();
These names all describe one probe job, but they are separate root variables. Later it becomes harder to see which values belong together.
It also becomes harder to run two similar jobs in the same session, because both jobs would want similar variable names.
Use a class when you want to create an object with fields that belong together.
class ProbeJob(feed) { safe_z = 5; probe_feed = feed; depth = -2; count = 0; last_x = none(); last_y = none(); last_z = none(); function AddCount() { count += 1; } } probe = ProbeJob(120); probe.AddCount();
Now the root session has one main name, `probe`, and the probe values are inside it. Fields can be read from outside the object, but changes should be done through methods or constructor arguments.
print('feed ', probe.probe_feed); print('count ', probe.count);
When an action belongs to the same data, put it in a method.
class ProbeJob() { safe_z = 5; feed = 100; count = 0; last_x = none(); last_y = none(); last_z = none(); function SetFeed(value) { feed = value; } function RecordHit(x, y, z) { count += 1; last_x = x; last_y = y; last_z = z; } } probe = ProbeJob(); probe.SetFeed(120); probe.RecordHit(10, 20, -1.25);
The method names show what the object is doing. The fields keep the result with the object that owns it.
Objects are useful when two jobs need the same kind of data.
left = ProbeJob(); right = ProbeJob(); left.SetFeed(80); right.SetFeed(120); left.RecordHit(10, 20, -1.10); right.RecordHit(50, 20, -1.35); print(left.last_z); print(right.last_z);
Each object has its own fields. Changing `left` does not change `right`.
Objects are also a good place for dialog and callback results.
class DialogResult() { accepted = false; action = ''; password = ''; function OnPassword(result) { accepted = result.ok; action = result.action; password = result.password; } } state = DialogResult(); dlg = msg_password(); dlg.title('Password'); dlg.message('Enter password'); dlg.on_result(state.OnPassword); dlg.show();
The callback updates `state`. The script does not need separate root variables such as `dialog_ok`, `dialog_action`, and `dialog_password`.
A useful pattern is to keep settings and results on the same object.
class ToolChangeJob() { tool = 0; safe_z = 20; feed = 300; completed = false; message = ''; function SetTool(number) { tool = number; } function SetSafeZ(value) { safe_z = value; } function SetFeed(value) { feed = value; } function Done(text) { completed = true; message = text; } } job = ToolChangeJob(); job.SetTool(3); job.Done('Tool changed');
This keeps the current job easy to inspect:
print(job.tool); print(job.completed); print(job.message);
Objects do not remove all root variables. They help you keep root variables intentional.
Good root variables are usually names such as:
Avoid turning one task into many unrelated root names:
job_tool = 3; job_safe_z = 20; job_feed = 300; job_completed = false; job_message = '';
Prefer one object and methods that change it:
job = ToolChangeJob(); job.SetTool(3); job.SetSafeZ(20); job.SetFeed(300);
Use simple variables when the value is temporary or when only one or two values are involved.
x = 10; y = 20; distance = sqrt(x*x + y*y);
An object is useful when the same values travel together, are used by several functions, or should stay in the session for later commands.
Use a class object when: