Unit 4: Object-Oriented Programming
Encapsulation is a core principle of Object-Oriented Programming that involves bundling data and methods into a single unit (a class) and restricting access to its internal state. It's like putting a protective case around your robot's delicate electronics.
Imagine if any part of your robot's code could directly command a motor. A bug in your vision code could accidentally cause your arm to move, leading to chaos. Encapsulation prevents this by controlling how data is accessed and modified.
We use the `private` access modifier to "hide" a class's important fields (like motor controllers and sensors). This means they can only be accessed by the methods inside that same class, preventing outside interference.
Since `private` fields are hidden, how do we interact with them? We provide `public` methods that act as controlled gateways to the data.
Let's look at a `Shooter` subsystem. We want to protect its motors and ensure we can't set an unsafe target speed.
public class Shooter {
// 1. Data Hiding: These fields are private and protected.
private Spark m_flywheelMotor;
private Encoder m_flywheelEncoder;
private double m_targetRPM;
// A constant for the safe operating limit of the motor.
private static final double MAX_RPM = 5000.0;
public Shooter(int motorPort, int encoderPortA, int encoderPortB) {
m_flywheelMotor = new Spark(motorPort);
m_flywheelEncoder = new Encoder(encoderPortA, encoderPortB);
m_targetRPM = 0.0;
}
// 2. Controlled Access: Public "setter" with validation.
public void setTargetRPM(double rpm) {
// Validation logic: only accept safe values.
if (rpm >= 0 && rpm <= MAX_RPM) {
this.m_targetRPM = rpm;
} else {
System.out.println("Error: Unsafe RPM value requested: " + rpm);
}
}
// Public "getter" to read the current speed.
public double getActualRPM() {
return m_flywheelEncoder.getRate(); // Assuming encoder is configured for RPM
}
// Another getter
public double getTargetRPM() {
return m_targetRPM;
}
}
Now, other parts of the code can't directly touch the motor. They must go through our safe, public methods.
// In a command or another part of the code:
Shooter robotShooter = new Shooter(10, 0, 1);
// This is safe and works as intended.
robotShooter.setTargetRPM(4500.0);
// This is also safe. The validation logic inside the setter will reject it.
robotShooter.setTargetRPM(9000.0); // Prints an error, m_targetRPM remains unchanged.
// This causes a COMPILE ERROR because m_flywheelMotor is private.
// robotShooter.m_flywheelMotor.set(1.0); // This is not allowed!
Question: What is the primary benefit of making a class's fields (like motor controllers) `private`?