1 / 42
Start
Abstract
Base
Interface
Final
Sealed
Factory
Mixins
Enums
Extensions
Q1
Q2
Project
Q3
Week 2 · Day 5

Advanced Classes

Control how your code is used. Real OOP toolkit — problem first, solution second.

Abstract Base Interface Final Sealed Factory Mixins Enums Extensions 3 Quizzes + Project

Press J anytime to jump to any section. Arrow keys to navigate.

Recap

Where We Left Off — Day 4

Quick reminder of everything you already know.

Git

init, add, commit, status

PRs

branches, review, merge

Restaurant

team project in groups

Classes

blueprint — properties + methods

Constructors

default + named (this.x shortcut)

Extends

child class reuses parent

📌 Today: more class tools. Problem → Solution for each.

The Plan

6 Class Modifiers — Quick Map

Each one controls who can use or extend your class.

abstract

Force children to fill in methods

base

Children must extend (not implement)

interface

Children only implement (no inheritance)

final

No children at all

sealed

Only these exact children allowed

factory

Smart way to create objects (bonus)

📌 We'll do each one with 3 slides: Why → How → Real Use.

Topic 1 · abstract

abstract — Incomplete Blueprint

🏗️

Form Template

Like a form template that says "you MUST fill in these fields." The template itself is useless — you need to fill it.

❌ WITHOUT abstract
class Payment {
void pay() { } // empty body
}

// Anyone can do:
Payment().pay(); // does nothing!
// Subclasses might forget pay() too.

📌 We need: force every payment type to have its OWN pay() code.

Topic 1 · abstract

How to Define abstract

abstract class Payment { // ← keyword
void pay(); // ← no body!
}
MINI DEMO
class Cash extends Payment {
@override
void pay() => print('💵 paid');
}

✅ CAN do

Declare methods with no body.

❌ CAN'T do

Create Payment() directly.

💡 Key rule

Children MUST write pay().

Topic 1 · abstract

Real Use — Payment Types

abstract class Payment {
void pay(int amount);
}

class Cash extends Payment {
@override
void pay(int amount) {
print('💵 Rs.$amount in cash');
}
}

class Esewa extends Payment {
@override
void pay(int amount) {
print('📱 Rs.$amount via eSewa');
}
}

void main() {
Payment p = Cash();
p.pay(500); // 💵 Rs.500 in cash
}
Topic 2 · base

base — Only Extend, Not Copy

🔒

Recipe Book

Like a recipe book. Chefs can add new recipes (extend). But no one can photocopy it and claim it's theirs (implement).

❌ WITHOUT base
class Account {
Account() {
print('Setting up safely');
}
}

class FakeAccount implements Account {
// constructor NEVER runs!
// Setup skipped 😱
}

📌 Sometimes we want: "Children must use MY setup."

Topic 2 · base

How to Define base

base class Account { // ← keyword
// children must extend
}
MINI DEMO
base class Savings extends Account {
// constructor of Account runs ✅
}

✅ CAN do

extends Account — allowed.

❌ CAN'T do

implements Account — blocked.

💡 Key rule

Child also must be base, final, or sealed.

Topic 2 · base

Real Use — Bank Accounts

base class Account {
final String owner;
double balance;

Account(this.owner, this.balance);
}

base class Savings extends Account {
double rate;

Savings(String owner, double bal, this.rate)
: super(owner, bal);
}

// ❌ class Fake implements Account {}
// Error — use extends instead
Topic 3 · interface

interface — Contract Only

📋

Job Description

Like a job description. "You must do task A and task B." But HOW you do them is up to you.

❌ WITHOUT interface
class Printable {
void print() {
// some default code
}
}

// Child extends — reuses code.
// But I wanted: 'just PROMISE to print()'
// Reuse not needed!

📌 Sometimes we want: "just the shape, no inherited code."

Topic 3 · interface

How to Define interface

interface class Printable { // ← keyword
void print() { } // body ignored
}
MINI DEMO
class Receipt implements Printable {
@override
void print() {
// my OWN code
}
}

❌ CAN'T do

extends Printable — blocked.

✅ CAN do

implements Printable — required.

💡 Key rule

Children rewrite ALL methods.

Topic 3 · interface

Real Use — Restaurant Greetings

interface class Greetable {
void greet();
}

class Waiter implements Greetable {
@override
void greet() => print('Namaste!');
}

class Menu implements Greetable {
@override
void greet() => print('Welcome to our menu');
}

// Both promise to greet, both do it differently
Topic 4 · final

final — No Children Allowed

🔐

Sealed Box

Like a sealed box. No one can open it, extend it, or copy its shape. Use as-is.

❌ WITHOUT final
class OrderId {
final String value;
OrderId(this.value);
}

// Anyone makes:
class HackId extends OrderId { ... }
class FakeId implements OrderId { ... }
// Risk: wrong IDs in system

📌 Sometimes we want: "no copies, no children, just this."

Topic 4 · final

How to Define final

final class OrderId { // ← keyword
final String value;
OrderId(this.value);
}

❌ CAN'T do

extends — blocked.

❌ CAN'T do

implements — blocked.

💡 Key rule

Use for value/ID classes.

Topic 4 · final

Real Use — IDs & Prices

final class OrderId {
final String value;
OrderId(this.value);
}

final class Price {
final int rupees;
Price(this.rupees);
}

// Use them:
var id = OrderId('ORD-001');
var price = Price(500);

// ❌ class BadId extends OrderId {} — error
Topic 5 · sealed

sealed — Fixed Family

🏠

Fixed Menu

Like a fixed menu. Only these 3 items exist — Momo, Thukpa, Dal Bhat. No one can add "Pizza" secretly.

❌ WITHOUT sealed
abstract class Payment {
void pay();
}
class Cash ...
class Card ...
class Esewa ...

// Another file:
class FakePay extends Payment { ... }
// 😱 Surprise new type!

📌 Sometimes we want: "Only these 3 subclasses. No more."

Topic 5 · sealed

How to Define sealed

sealed class Payment { // ← keyword
void pay(int amount);
}

class Cash extends Payment {
@override
void pay(int a) => print('cash');
}

✅ CAN do

Fixed children — same file only.

💡 Key rule

Works great with switch.

🎁 Bonus

Compiler checks ALL cases.

Topic 5 · sealed

Real Use — Exhaustive Switch

sealed class Payment {
void pay(int amount);
}

class Cash extends Payment {
@override
void pay(int a) => print('💵 Rs.$a');
}

class Esewa extends Payment {
@override
void pay(int a) => print('📱 Rs.$a');
}

String icon(Payment p) {
return switch (p) {
Cash() => '💵',
Esewa() => '📱',
// compiler forces all cases!
};
}

📌 Miss a case? Compiler error. Zero bugs.

Summary

Which Modifier to Pick?

Q1: Does class work alone?
 ├─ NO  → abstract
 └─ YES ↓

Q2: Want children at all?
 ├─ NO  → final
 └─ YES ↓

Q3: Only specific children?
 ├─ YES → sealed
 └─ NO  ↓

Q4: Share code with children?
 ├─ YES → base
 └─ NO  → interface
🎮 Quiz 1 · Modifiers

Test Your Modifier Knowledge

1. abstract class means?

ALocked class
BChildren must fill methods
CNo constructor
✅ abstract forces every child to implement the empty methods.

2. sealed gives you?

AMore speed
BFixed children + exhaustive switch
CNo inheritance at all
✅ sealed locks the family. The compiler then checks every case in switch.

3. final class blocks?

ABoth extend and implement
BOnly extend
COnly implement
✅ final blocks BOTH. No children, no copies.
Topic 6 · factory

factory — Smart Creation

🏭

Drink Machine

Like a drink machine. You press "cola" — the machine picks the right can. You don't pick cans directly.

❌ REGULAR CONSTRUCTOR
// ALWAYS makes new object
var p = Payment();

// Cannot return subtype
// Cannot pick Cash vs Card
// based on input

📌 Sometimes we want: "pick which class based on input."

Topic 6 · factory

How to Define factory

class Payment {
factory Payment(String type) { // ← keyword
if (type == 'cash') return Cash();
if (type == 'card') return Card();
throw 'Unknown';
}
}

✅ CAN do

Return any subtype.

✅ CAN do

Return cached object.

💡 Key rule

Uses return — no this.

Topic 6 · factory

Real Use — Payment Factory

abstract class Payment {
void pay(int amount);

factory Payment.of(String type) {
if (type == 'cash') return Cash();
if (type == 'esewa') return Esewa();
throw 'Unknown: $type';
}
}

class Cash extends Payment {
@override
void pay(int a) => print('💵 Rs.$a');
}

class Esewa extends Payment {
@override
void pay(int a) => print('📱 Rs.$a');
}

void main() {
var p = Payment.of('cash');
p.pay(500); // 💵 Rs.500
}
🎮 Quiz 2 · Factory

Test Your Factory Knowledge

1. A factory can?

AOnly make a new object
BReturn a subtype or cached object
CDelete objects
✅ factory can decide what to return — new, subtype, or cached.

2. What's the normal constructor's limit?

AAlways creates new, can't pick subtype
BIt's slow
CCan't have a body
✅ Normal constructors always build a fresh object of THAT class.

3. Inside a factory you use?

Athis
Breturn keyword
Cnew
✅ A factory returns an object explicitly with return.
Topic 7 · Mixins

mixin — Share Skills

🔌

USB Skill Stick

Like a USB skill stick. Plug the same skill into many devices. Camera, phone, laptop all get it.

❌ WITHOUT mixins
class Savings {
void log(String m) { ... } // copy
}
class Current {
void log(String m) { ... } // paste
}
class Fixed {
void log(String m) { ... } // paste again
}
// 3 copies of same code 😱

📌 We want: write once, use in many classes.

Topic 7 · Mixins

How to Define a mixin

mixin Loggable { // ← keyword
void log(String message) {
print('📝 $message');
}
}

class Savings with Loggable { } // ← use

✅ CAN do

Many classes use the same mixin.

✅ CAN do

Class can use many mixins.

💡 Key rule

No extends — uses with.

Topic 7 · Mixins

Real Use — Order Skills

mixin Loggable {
void log(String m) => print('📝 $m');
}

mixin Printable {
void printReceipt() => print('=== receipt ===');
}

class Order with Loggable, Printable {
int total = 0;
}

void main() {
var o = Order();
o.log('order placed');
o.printReceipt();
}

📌 Order class gets both log() and printReceipt() for free.

Topic 7 · Mixins

onConstrain Where Mixin Used

❌ PROBLEM

Mixin needs a field from parent? E.g. balance?

mixin Discountable {
void discount() {
balance *= 0.9; // ❌ where's balance?
}
}
✅ SOLUTION: on
abstract class Account {
double balance = 0;
}

mixin Discountable on Account {
void discount() {
balance *= 0.9; // ✅ works now
}
}

class Savings extends Account with Discountable { }

📌 on Account = "only classes extending Account can use me."

Topic 8 · Enhanced Enums

Enums with Data Inside

🏷️

Labeled Box

Like a labeled box. Box says "Savings" and inside is the rate (5%). Label + data together.

❌ BASIC ENUM
enum AccountType { savings, current }

// Where do I store rate per type?
double getRate(AccountType t) {
if (t == AccountType.savings) return 5;
if (t == AccountType.current) return 0;
return 0;
}
// Data scattered 😕

📌 We want: data lives INSIDE the enum.

Topic 8 · Enhanced Enums

How to Define an enhanced enum

enum AccountType {
savings(5.0), // ← pass value
current(0.0);

final double rate; // ← field
const AccountType(this.rate); // ← constructor
}

✅ CAN do

Fields stored with value.

✅ CAN do

Methods allowed.

💡 Key rule

Must use const constructor.

Topic 8 · Enhanced Enums

Real Use — Order Status

enum OrderStatus {
pending('⏳'),
cooking('🍳'),
done('✅');

final String icon;
const OrderStatus(this.icon);
}

void main() {
var s = OrderStatus.cooking;
print('${s.icon} ${s.name}');
// 🍳 cooking

for (var st in OrderStatus.values) {
print('${st.icon} ${st.name}');
}
}
Topic 9 · Extensions

extension — Add Methods to Any Class

Sticker

Like a sticker. Stick a new button on an existing TV remote. Can't open the remote, but you added a feature.

❌ WITHOUT extension
// Want: '500'.toRupees() → 'Rs.500'
// But String is built-in. Can't edit!

String toRupees(String s) {
return 'Rs.$s';
}
toRupees('500'); // ugly function call

📌 We want: add method to built-in class without editing it.

Topic 9 · Extensions

How to Define an extension

extension on String { // ← keyword
String toRupees() {
return 'Rs.$this'; // ← this = the string
}
}

✅ CAN do

Add methods to ANY class.

✅ CAN do

Even String, int, List.

💡 Key rule

Use this to refer to the object.

Topic 9 · Extensions

Real Use — Rupees & Phones

extension on int {
String get rupees => 'Rs.$this';
}

extension on String {
bool get isNepaliPhone {
return length == 10 && startsWith('98');
}
}

void main() {
print(500.rupees); // Rs.500
print('9841234567'.isNepaliPhone); // true
print('123'.isNepaliPhone); // false
}
🎮 Project · Payment System

Build the Payment System

Everything from today — abstract, factory, sealed, mixins, extensions. Click each feature.

🏗️ Abstract
🏭 Factory
🔐 Sealed
🔌 Mixin
✨ Extension
CONCEPTS USED
🎮 Quiz 3 · Advanced

Mixins, Enums & Extensions

1. with keyword is used for?

AInheritance
BUsing mixins
CCalling a constructor
✅ with plugs in a mixin's methods. extends is for inheritance.

2. An enhanced enum can have?

AOnly names
BFields + methods + const constructor
COnly numbers
✅ Enhanced enums hold data (fields) and behavior (methods).

3. An extension lets you?

AEdit the original source
BAdd methods without changing the class
CDelete methods
✅ Extensions attach methods to existing types without touching them.
Summary

6 Modifiers Recap

abstract

Force implementation

base

Only extend

interface

Only implement

final

No children

sealed

Fixed family

factory

Smart creation

Summary

Advanced Tools Recap

Mixins

Share skills (with, on)

Enhanced Enums

Data + methods

Extensions

Add methods anywhere

Quick Reference

When to Use What

Need force methods?

→ abstract

Fixed list of types?

→ sealed

Lock class down?

→ final

Share code across classes?

→ mixin

Fixed values with data?

→ enhanced enum

Add method to String/int?

→ extension
Assignment

Take-Home: Extend Payment System

1. Add Khalti and IME to sealed Payment
2. Mixin Loggable on all payments
3. Enhanced enum OrderStatus with icon field
4. Extension on int for .rupees
5. factory Payment.of(String)
6. Push to GitHub via PR

Use branches! Create feature/your-name and submit a PR.

Coming Next

Day 6 — Libraries & Packages

import your own files dart:math Random pub.dev http package

Before next class: finish your Payment System assignment and push to GitHub.

Any Questions?

Practice at dartpad.dev — try rebuilding the Payment System from scratch!