-
Notifications
You must be signed in to change notification settings - Fork 20
ClassDefinition_step4
RoiArthurB edited this page Jul 30, 2026
·
4 revisions
A virtual class cannot be instantiated directly. It acts as a contract — every concrete subclass must implement all declared virtual actions.
class sensor virtual: true {
string id <- "sensor";
bool active <- true;
// Virtual (abstract) action: every concrete subclass MUST implement
float read() virtual: true;
// Virtual action: every concrete subclass MUST implement
string unit() virtual: true;
// Concrete action: implemented once here, calls the virtual actions
string formatted_reading() {
if !active { return id + ": [OFF]"; }
return id + ": " + (read() with_precision 2) + " " + unit();
}
}
The sensor class:
- Cannot be instantiated:
sensor s <- sensor()yields nil (sis nil). - Acts as a contract: every subclass must implement
read()andunit(). - Provides a concrete
formatted_reading()that calls the virtual actions polymorphically.
A concrete class (no virtual: true) must implement every inherited virtual action:
class thermometer parent: sensor {
float temperature <- 20.0;
float min_temp <- #infinity;
float max_temp <- -#infinity;
// Implements sensor.read()
float read() {
return temperature;
}
// Implements sensor.unit()
string unit() {
return "°C";
}
action update(float t) { // new action specific to thermometer
temperature <- t;
if t < min_temp { min_temp <- t; }
if t > max_temp { max_temp <- t; }
}
}
class barometer parent: sensor {
float pressure <- 1013.25;
// Implements sensor.read()
float read() {
return pressure;
}
// Implements sensor.unit()
string unit() {
return "hPa";
}
// Specific action not part of the sensor contract
float estimated_altitude() {
return 44330.0 * (1.0 - (pressure / 1013.25) ^ 0.1903);
}
}
If a child class does not implement ALL virtual actions from its parent, it becomes virtual itself (and cannot be instantiated).
A class that implements SOME but not all virtual actions from its parent becomes virtual itself:
class calibrated_sensor virtual: true parent: sensor {
float calibration_offset <- 0.0;
// Implements unit() from sensor — concrete
string unit() {
return "raw";
}
// read() is still virtual here — calibrated_sensor is itself abstract
// You cannot instantiate this class
}
class light_sensor parent: calibrated_sensor {
float raw_lux <- 0.0;
// Finally implements read() from sensor → light_sensor is CONCRETE
float read() {
return raw_lux + calibration_offset;
}
// Override the "raw" unit from calibrated_sensor
string unit() {
return "lux";
}
}
Hierarchy:
sensor (abstract)
├── thermometer (concrete)
├── barometer (concrete)
└── calibrated_sensor (abstract — still needs read())
└── light_sensor (concrete — implements read + overrides unit)
A variable typed as the virtual class can hold any concrete subclass:
list<sensor> sensors <- [
thermometer(id: "temp01", temperature: 23.5),
barometer(id: "baro01", pressure: 1005.0),
light_sensor(id: "lux01", raw_lux: 850, calibration_offset: 15)
];
loop s over: sensors {
write s.formatted_reading(); // dispatches to the concrete class's read() and unit()
}
float max_r <- max(sensors collect (each.active ? each.read() : -#infinity));
write "max raw reading = " + (max_r with_precision 2);
You can only access concrete-specific methods (not in the abstract class) after narrowing down to the right type:
// barometer-specific: estimated_altitude() is NOT defined on sensor
loop s over: sensors {
if s is barometer {
barometer b <- s; // cast to barometer
write b.estimated_altitude() with_precision 0 + " m";
}
}
if t1 is sensor {
// OK — thermometer is a sensor
}
if l1 is calibrated_sensor {
// OK — light_sensor extends calibrated_sensor which extends sensor
}
if t1 is barometer {
// false — thermometer and barometer are siblings
}
class sensor virtual: true {
string id <- "sensor";
bool active <- true;
float read() virtual: true;
string unit() virtual: true;
string formatted_reading() {
if !active { return id + ": [OFF]"; }
return id + ": " + (read() with_precision 2) + " " + unit();
}
}
class thermometer parent: sensor {
float temperature <- 20.0;
float min_temp <- #infinity;
float max_temp <- -#infinity;
float read() { return temperature; }
string unit() { return "C"; }
action update(float t) {
temperature <- t;
if t < min_temp { min_temp <- t; }
if t > max_temp { max_temp <- t; }
}
}
class barometer parent: sensor {
float pressure <- 1013.25;
float read() { return pressure; }
string unit() { return "hPa"; }
}
global {
init {
list<sensor> sensors <- [
thermometer(id: "temp01", temperature: 23.5),
barometer(id: "baro01", pressure: 1005.0)
];
// Polymorphic dispatch
loop s over: sensors {
write s.formatted_reading();
}
// Toggle off
sensors[1].active <- false;
loop s over: sensors {
write s.formatted_reading(); // barometer now prints [OFF]
}
}
}
experiment Virtual_Classes title: "Virtual Classes" type: gui {}
| Feature | Syntax |
|---|---|
| Abstract class | class ClassName virtual: true { |
| Virtual action | return_type action_name() virtual: true; |
| Implement inherited virtual action | Redefine with the same signature (no virtual: true) |
| Partially abstract intermediate | Implements some virtual actions → becomes virtual itself |
| Polymorphic list | list<AbstractClass> items <- [concrete1, concrete2]; |
| Type check | obj is ConcreteClass |
- Installation and Launching
- Workspace, Projects and Models
- Editing Models
- Running Experiments
- Running Headless
- Preferences
- Troubleshooting
- Introduction
- Manipulate basic Species
- Global Species
- Defining Advanced Species
- Defining GUI Experiment
- Classes and Objects
- Exploring Models
- Optimizing Models
- Multi-Paradigm Modeling
- Manipulate OSM Data
- Cleaning OSM Data
- Diffusion
- Using Database
- Using Dataframes
- Using FIPA ACL
- Using BDI with BEN
- Using Driving Skill
- Manipulate dates
- Manipulate lights
- Using comodel
- Save and restore Simulations
- Using network
- Writing Unit Tests
- Ensure model's reproducibility
- Going further with extensions
- Built-in Species
- Built-in Skills
- Built-in Architecture
- Statements
- Data Type
- File Type
- Stats Extension
- Sound Extension
- BDI Extension
- FIPA Skill
- Expressions
- Exhaustive list of GAMA Keywords
- Installing the development version
- Developing Extensions
- Introduction to GAMA Java API
- Using GAMA flags
- Creating a release of GAMA
- Documentation generation
- Predator Prey
- Road Traffic
- Incremental Model
- Luneray's flu
- BDI Agents
- Forager RL
- SIR Analysis
- 3D Model