Classes and Objects#
Classes are the blueprints of a Java program.
Overview#
Java is an object-oriented language. Almost everything in Java is an object — a bundle of data and behavior — and classes are the blueprints that define what an object looks like and what it can do.
In FRC, every subsystem, every command, and every piece of configuration is its own class. Many of these classes are provided for you by the WPILib or other libraries, but you will also write your own to define your robot's unique behavior.
What is a Class?#
A class is a template that defines a type of object. Classes contains:
- Fields — variables that store the object's state (e.g., motor controllers, sensors)
- Methods — functions that define what the object can do (e.g.,
setSpeed,stop) - A constructor — a special method that sets the object up when it is first created
Note
Classes are typically defined in their own file, and the file name must match the class name exactly (including capitalization). For example, a class named Drivetrain must be in a file named Drivetrain.java.
Declaring a Class#
package— declares which folder this file lives in.frc.robot.subsystemsmaps to the directory pathfrc/robot/subsystems/inside your project.import— makes a class available in this file by its short name. Without an import you would have to write the full path every time — e.g.,edu.wpi.first.wpilibj2.command.SubsystemBaseinstead of justSubsystemBase.public— this class can be used by other classes in the project. (If you omit this, the class is only visible within its own package.)class Drivetrain— the class name, which must match the file name exactlyextends SubsystemBase— WPILib providesSubsystemBaseas the foundation for every robot subsystem. Extending it gives your class the scheduling hooks, periodic updates, and other plumbing the robot framework needs to run it. (see Inheritance)
Packages and imports in VSCode
VSCode can add import statements automatically. When the editor underlines a class name in red because it is not imported, click the 💡 light bulb (or press ++ctrl+period++) and choose the correct import. See VSCode Tips.
Fields#
Fields (also called instance variables or member variables) store the object's data. They are declared at the top of the class body, outside any method. Variables should be declared here if they represent something that is part of the object's state, such as motor controllers or configuration values, or if they need to be accessed by multiple methods in the class.
What is a SparkMax / TalonFX?
A SparkMax (REV Robotics) and a TalonFX (CTRE) are motor controllers — small electronic devices that connect to a motor and control how fast it spins. In FRC code, you declare one field per physical motor controller on your robot. Both are among the most common motor controllers used in FRC.
Access Modifiers#
| Modifier | Meaning |
|---|---|
public |
Any class can read or modify this |
private |
Only this class can access it |
protected |
This class and any subclasses can access it |
Tip
Default to private for fields. This prevents other classes from accidentally changing values they should not touch. Expose data only through public methods when needed. Accessing and setting protected fields is typeically done through "getter" and "setter" methods. This is called encapsulation and is a core principle of object-oriented programming.
Constructors#
A constructor is a special method that runs exactly once — when an object is created with new. Its job is to initialize all the fields and any other necessary setup.
- The constructor name must exactly match the class name
- Constructors have no return type (not even
void) - If the class requires parameters to set up, those must be listed in the constructor definition, inside the parentheses. (see the [this] section (#this))
- When you create an object with
new, you must provide arguments that match the constructor's parameters.
Note
If you do not write a constructor, Java provides a default no-argument constructor that does nothing.
Info
More about constructors here: Java Constructors
The new Keyword#
new creates an object from a class and calls its constructor:
The variable on the left holds a reference to the object — think of it as a label pointing to the object in memory.
this#
Inside a class, this refers to the current object. It is most commonly used when a constructor parameter has the same name as a field — without this, Java cannot tell which one you mean:
public class Drivetrain extends SubsystemBase {
private double topSpeed;
public Drivetrain(double topSpeed) {
this.topSpeed = topSpeed; // "this.topSpeed" is the field; "topSpeed" alone is the parameter
}
}
Inheritance#
A class can extend another class to inherit all of its fields and methods. The class being extended is the parent (or superclass); the extending class is the child (or subclass).
Think of it like categories in real life: a Dog is an Animal — it automatically has everything that comes with being an animal (it breathes, it moves), plus its own extras (it barks). In the same way, Drivetrain extends SubsystemBase means your drivetrain automatically has everything WPILib built into SubsystemBase, plus whatever drive logic you add.
public class Drivetrain extends SubsystemBase {
// Drivetrain automatically has everything SubsystemBase provides
}
In FRC:
- All subsystems extend
SubsystemBase - Commands extend
Commandor are created via command factory methods on subsystems
Inheritance lets you build on top of pre-built FRC plumbing without writing it from scratch.
@Override#
When a child class replaces a method from the parent, it marks it with @Override:
@Override
public void periodic() {
// Replaces the empty version in SubsystemBase;
// runs every robot loop cycle
}
The annotation is optional but recommended — if you misspell the method name, the compiler will tell you there is nothing to override, catching the typo early.
A method that is overridden replaces the parent version completely with your own implementation. If you want to run the parent method as well, you can call it with super:
@Override
public void periodic() {
super.periodic(); // runs the parent version (if it does anything)
// then add your own code here
}
Putting It Together#
A complete minimal subsystem class
package frc.robot.subsystems;
import com.revrobotics.spark.SparkMax;
import com.revrobotics.spark.SparkLowLevel.MotorType;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class Drivetrain extends SubsystemBase {
private final SparkMax leftLeader;
private final SparkMax rightLeader;
public Drivetrain() {
leftLeader = new SparkMax(1, MotorType.kBrushless);
rightLeader = new SparkMax(2, MotorType.kBrushless);
}
public void setSpeed(double speed) {
leftLeader.set(speed);
rightLeader.set(speed);
}
@Override
public void periodic() {
// Update dashboard values here if needed
}
}
package frc.robot.subsystems;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.controls.DutyCycleOut;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class Drivetrain extends SubsystemBase {
private final TalonFX leftLeader;
private final TalonFX rightLeader;
public Drivetrain() {
leftLeader = new TalonFX(1);
rightLeader = new TalonFX(2);
}
public void setSpeed(double speed) {
leftLeader.setControl(new DutyCycleOut(speed));
rightLeader.setControl(new DutyCycleOut(speed));
}
@Override
public void periodic() {
// Update dashboard values here if needed
}
}
Note
private final on the fields means each motor controller is assigned once in the constructor and never swapped out. See Variables and Data Types for more on final.
Knowledge Check#
Quiz results are saved to your browser's local storage and will persist between sessions.
What runs automatically the moment you use the new keyword to create an object?
Which access modifier makes a field accessible only within the class it is declared in?
Inside a class, what does this refer to?
Which keyword is used to inherit fields and methods from another class?
What is the correct term for the class that is being inherited from?
Quiz Progress
0 / 0 questions answered (0%)
0 correct