Irbisa · Cheatsheet
OOP in Dart
Classes, inheritance, interfaces, mixins, and abstract classes
What are the four OOP principles, and how does each one look in Dart?
How do constructors work in Dart (generative, named and initializer lists), and why must
finalfields be set before the body?class Point { final double x; final double y; // generative: fields set straight from parameters Point(this.x, this.y);…What is a
factoryconstructor, how does it differ from a generative one, and can it returnnullor a cached instance?class Logger { Logger._internal(this.name); final String name; static final _cache = <String, Logger>{};…What does
super.keyin a widget constructor do, and when can you not use super parameters?class Avatar extends StatelessWidget { // before: const Avatar({Key? key, required this.url}) : super(key: key); const Avatar({super.key, required this.url, this.size = 40}); final String url; final double size;…Does Dart support method overloading, and how do you get the same effect?
class Toast { // one method instead of show(text), show(text, duration), show(text, duration, action) static void show( String text, { Duration duration = const Duration(seconds: 2), String? actionLabel,…Dart has no
privatekeyword. How does_privacy work, and what does a._()constructor mean?// cart.dartclass Cart { Cart._(); // private: other files cannot call it static final instance = Cart._(); final _items = <String>[]; // private to cart.dart…How do getters and setters work in Dart, and why can a public field become a getter without breaking callers?
class CartItem { CartItem(this.price, this._quantity); final double price; int _quantity; int get quantity => _quantity;…When should a member be
static, and what can static members not do?What is the difference between
extends,implementsandwith, and where does an abstract class fit in?abstract class Shape { double get area; // abstract: subclasses must provide it String describe() => 'area ${area.toStringAsFixed(1)}'; // inherited} mixin Loggable {…What is a mixin, when do you use one instead of inheritance, and what does the
onclause do?mixin Validator { // abstract: the host class must provide it Map<String, String?> get fields; bool get isValid => fields.values.every((v) => v != null && v.isNotEmpty);}…What are extension methods, what do they give you over helper functions, and when do they not apply?
extension StringCase on String { String capitalize() => isEmpty ? this : '${this[0].toUpperCase()}${substring(1)}';} extension ContextX on BuildContext {…How does operator overloading work in Dart, and which operators can you overload?
final class Money { const Money(this.cents); final int cents; Money operator +(Money other) => Money(cents + other.cents); Money operator *(int times) => Money(cents * times);…This
Setwas meant to drop the duplicate but prints2. What is missing, and what happens if you mutate an object already in the set?class Point { Point(this.x, this.y); int x, y; @override bool operator ==(Object other) => other is Point && other.x == x && other.y == y;} void main() { final points = {Point(1, 2), Point(1, 2)}; print(points.length);}What is a callable class (a class with a
call()method), and when would you write one?abstract interface class UserRepository { Future<String> nameOf(String id);} class GetUserName { GetUserName(this._repo);…Why are Flutter widgets and models immutable, and how do you enforce immutability in Dart (
final,@immutable,copyWith)?@immutableclass Profile { Profile({required this.name, this.email, List<String> tags = const []}) : tags = List.unmodifiable(tags); final String name;…What is a
constconstructor, and why does Flutter preferconstwidgets?class Point { const Point(this.x, this.y); // all fields final, no body final int x, y;} void main() {…What do the Dart 3 class modifiers
base,interface,final,sealedandmixin classcontrol?// interface: others implement it, nobody inherits your bodiesabstract interface class UserRepository { Future<String> nameOf(String id);} // base: others may extend, never implement, so _send always runs…Why does Flutter favour composition over inheritance, and how would you refactor a bloated
BaseScreenbase class?// before: class ProfileScreen extends BaseScreen { /* six overridden hooks */ } // after: the shared part is a widget the screens composeclass AsyncView<T> extends StatelessWidget { const AsyncView({super.key, required this.snapshot, required this.builder});…Find the bug: in an integration test,
ApiClient(baseUrl: server.url)still sends requests to the production API.class ApiClient { ApiClient._(this.baseUrl); final String baseUrl; static ApiClient? _instance; factory ApiClient({required String baseUrl}) => _instance ??= ApiClient._(baseUrl); Uri endpoint(String path) => Uri.parse('$baseUrl$path');}What does this code print, and why does swapping
with Caching, Loggingtowith Logging, Cachingchange the output?class Base { String fetch() => 'base';} mixin Caching on Base { @override String fetch() => 'cache(${super.fetch()})';}mixin Logging on Base { @override String fetch() => 'log(${super.fetch()})';} class Repo extends Base with Caching, Logging {} void main() => print(Repo().fetch());Calling
Screen('home')throwsLateInitializationError. What is Dart's construction order, and how do you fix it?class Base { Base() { onInit(); } void onInit() {}} class Screen extends Base { Screen(this.title) : upper = title.toUpperCase() { controller = 'controller for $title'; } final String title, upper; late final String controller; @override void onInit() => print('$title $upper $controller');}Find the bug:
cart.contains(item)returnstrueorfalsefor the same product depending on whether the cart holds the plain or the sale version.class Product { Product(this.id); final String id; @override bool operator ==(Object other) => other is Product && other.id == id; @override int get hashCode => id.hashCode;}class SaleProduct extends Product { SaleProduct(super.id, this.discount); final int discount; @override bool operator ==(Object other) => other is SaleProduct && other.id == id && other.discount == discount; @override int get hashCode => Object.hash(id, discount);}