toString() Override
Part of the Object Oriented Programming section of Coddy's Dart journey — lesson 70 of 110.
When you print an object in Dart, you might see something like Instance of 'Person' - not very helpful. This happens because every class inherits a default toString() method from Object that only returns the class name.
By overriding toString(), you can provide a meaningful string representation of your objects:
class Person {
String name;
int age;
Person(this.name, this.age);
@override
String toString() {
return 'Person(name: $name, age: $age)';
}
}
void main() {
var person = Person('Alice', 30);
print(person); // Person(name: Alice, 30)
}Without the override, print(person) would output Instance of 'Person'. With it, you get useful information about the object's state.
The toString() method is called automatically whenever Dart needs to convert your object to a string - in print() statements, string interpolation, or when concatenating with other strings:
var message = 'User: $person'; // toString() called automatically
print('Found: ' + person.toString()); // Explicit callA well-implemented toString() makes debugging much easier by letting you quickly inspect object values during development.
Challenge
EasyLet's build a product catalog system where each product displays its information in a clean, readable format when printed. You'll practice overriding the toString() method to make your objects more debuggable and user-friendly.
You'll organize your code into two files:
product.dart: Create aProductclass that represents an item in a store. Your product should have aname(String),price(double), andquantity(int). Override thetoString()method to return a formatted string in this exact format:Product(name: [name], price: $[price], qty: [quantity])main.dart: Import your product file and demonstrate how thetoString()override makes printing objects much more useful. Create three products and print them to see your custom string representation in action:- A product named
'Laptop'with price999.99and quantity5 - A product named
'Mouse'with price29.5and quantity50 - A product named
'Keyboard'with price75.0and quantity30
Featured: [product]using the Laptop product.- A product named
Notice how printing each product directly shows meaningful information instead of the unhelpful Instance of 'Product' message. Your toString() method is called automatically both in print() statements and when using string interpolation.
Expected output:
Product(name: Laptop, price: $999.99, qty: 5)
Product(name: Mouse, price: $29.5, qty: 50)
Product(name: Keyboard, price: $75.0, qty: 30)
Featured: Product(name: Laptop, price: $999.99, qty: 5)Cheat sheet
By default, printing an object in Dart shows Instance of 'ClassName'. Override the toString() method to provide meaningful string representations:
class Person {
String name;
int age;
Person(this.name, this.age);
@override
String toString() {
return 'Person(name: $name, age: $age)';
}
}The toString() method is called automatically in print() statements and string interpolation:
var person = Person('Alice', 30);
print(person); // Person(name: Alice, age: 30)
var message = 'User: $person'; // toString() called automaticallyTry it yourself
import 'product.dart';
void main() {
// TODO: Create three Product instances:
// 1. Laptop - price: 999.99, quantity: 5
// 2. Mouse - price: 29.5, quantity: 50
// 3. Keyboard - price: 75.0, quantity: 30
// TODO: Print each product (toString() will be called automatically)
// TODO: Print a featured message using string interpolation
// Format: Featured: [laptop product]
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesLibraries & ImportsIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsInstance VariablesConstructor BasicsRecap - Simple Calculator4Null Safety
Intro to Null SafetyNullable vs Non-NullableThe ? and ! OperatorsLate Keyword & Null SafetyNull-Aware OperatorsNull Safety in ClassesRecap - User Profile System7Abstract Classes & Interfaces
Abstract ClassesAbstract MethodsInterfaces in DartImplicit InterfacesImplementing vs ExtendingMultiple InterfacesRecap - Shape Calculator10Collections & Generics
List, Set, Map OverviewType-Safe CollectionsGeneric ClassesGeneric MethodsGeneric ConstraintsIterable & IteratorRecap - Generic Storage13Advanced OOP Concepts
Composition vs InheritanceExtension MethodsCallable ClassesSealed Classes (Dart 3)Records (Dart 3)Patterns & Matching (3.0)Enums with Methods16Project: Library Management
Project OverviewBook and User Classes2Constructors in Dart
Default ConstructorNamed ConstructorsInitializer ListsConstant ConstructorsFactory ConstructorsRedirecting ConstructorsRecap - Shape Builder5Encapsulation
Public vs Private MembersThe _ Prefix ConventionLibrary-Level PrivacyGetters & Setters DepthInformation HidingRecap - Student Records8Mixins
Introduction to MixinsCreating MixinsUsing Multiple Mixinson Keyword in MixinsMixin vs InheritanceMixin vs InterfaceRecap - Animal System11Special Methods
toString() OverridehashCode & == OverrideComparable Interfacecall() MethodnoSuchMethod OverrideRecap - Custom Collection14Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern3Class Properties
Instance vs Static MembersFinal & Const FieldsLate VariablesStatic Methods & FieldsGetters and SettersRecap - Bank Account Manager6Inheritance
Basic InheritanceThe super KeywordMethod OverridingThe @override AnnotationThe final Class KeywordConstructors & InheritanceRecap - Employee Hierarchy9Polymorphism
Polymorphism BasicsPolymorphism via InterfacesRuntime Type CheckingThe is & as OperatorsCovariant KeywordRecap - Payment Processor