Classes & Objects
Blueprints for Building Anything in Dart
Open interactive version (quiz + challenge)Real-world analogy
What is it?
A class is a blueprint that defines a type of object by bundling together properties (data) and methods (behavior). When you create an object from a class, you get an instance with its own copy of the properties. Dart is a fully object-oriented language -- even numbers and functions are objects. In Flutter, everything from the app itself (MaterialApp) to the tiniest icon is an instance of a class.
Real-world relevance
Classes are the fundamental building blocks of every Flutter app. In team_mvp_kit, UserEntity represents a user, AuthRepository handles login logic, and AuthBloc manages authentication state. Without classes, you would have loose variables and functions with no organization -- like having a kitchen with no drawers or cabinets. Classes give your code structure, reusability, and clarity.
Key points
- Defining a Class — Use the class keyword to create a blueprint. A class groups related data (properties) and behavior (methods) together. Every entity, model, and widget in Flutter is a class.
- Properties (Fields) — Properties are variables that belong to a class. They store the data each object carries around. In team_mvp_kit, UserEntity has properties like id, name, and email.
- Methods — Methods are functions defined inside a class. They describe what an object can do. Methods can access the object's properties using the this keyword or just by name.
- Creating Objects (Instances) — You create an object by calling the class name like a function. Each object is independent -- changing one does not affect the others.
- The this Keyword — Inside a class, this refers to the current object. It is commonly used in constructors to assign parameters to properties, especially when parameter names match property names.
- Getters and Setters — Getters let you compute a value from properties. Setters let you validate or transform data before storing it. Use the get and set keywords.
- Private Members — Dart uses an underscore prefix to make properties and methods private to their library (file). Private members cannot be accessed from outside the file where the class is defined.
- Static Members — Static properties and methods belong to the class itself, not to any object. You access them using the class name. Great for utility functions and constants.
- toString Override — Every Dart class inherits from Object and has a toString method. Override it to give your objects a meaningful string representation, which helps with debugging.
- Classes in team_mvp_kit — The project uses classes everywhere: entities in the domain layer, models in the data layer, BLoC classes for state management, and repository classes for data access. Each layer has its own class hierarchy.
Code example
class UserEntity {
final String id;
final String name;
final String email;
const UserEntity({
required this.id,
required this.name,
required this.email,
});
String get initials {
final parts = name.split(' ');
if (parts.length >= 2) {
return '${parts[0][0]}${parts[1][0]}'.toUpperCase();
}
return name[0].toUpperCase();
}
@override
String toString() => 'UserEntity(id: $id, name: $name)';
}
void main() {
final user = UserEntity(
id: 'u-001',
name: 'Alice Smith',
email: 'alice@example.com',
);
print(user.initials); // AS
print(user); // UserEntity(id: u-001, name: Alice Smith)
}Line-by-line walkthrough
- 1. Define a class called UserEntity -- this is our blueprint for user objects
- 2. Declare a final String property id -- each user has a unique identifier
- 3. Declare a final String property name -- stores the user's display name
- 4. Declare a final String property email -- stores the user's email address
- 5. Mark the constructor as const since all fields are final -- allows compile-time constant objects
- 6. The constructor uses required named parameters with this.id, this.name, this.email for concise assignment
- 7. Define a getter called initials that computes the user's initials from their name
- 8. Split the name by spaces into a list of parts
- 9. If there are at least 2 parts, take the first character of each and uppercase them
- 10. Otherwise fall back to just the first character of the name, uppercased
- 11. Override toString from Object to return a readable string for debugging
- 12. In main, create a UserEntity instance using the named constructor parameters
- 13. Pass id, name, and email as required named arguments
- 14. Print user.initials which computes and returns AS
- 15. Print the user object which automatically calls our toString override
Spot the bug
class Counter {
int count = 0;
void increment() {
count++;
}
void reset() {
int count = 0;
}
}Need a hint?
Show answer
Explain like I'm 5
Fun fact
Hands-on challenge
More resources
- Dart Classes Documentation (dart.dev)
- Flutter Widget Class Reference (api.flutter.dev)
- Dart Language Tour - Classes (dart.dev)