Skip to content

Commit dd64ed9

Browse files
committed
feat: enhance class examples with test cases and improve README documentation
1 parent b791138 commit dd64ed9

9 files changed

Lines changed: 106 additions & 60 deletions

File tree

  • exercises
    • 01.classes
    • 02.interfaces-and-classes
      • 01.problem.implementing-interfaces
      • 02.problem.programming-to-abstractions
    • 03.inheritance
    • 04.polymorphism/01.problem.substitutability
    • 05.composition-vs-inheritance/01.problem.when-to-use

exercises/01.classes/01.problem.class-basics/index.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,23 @@
55
// - Constructor to initialize both
66
// - Method: getDescription() returns "Product: {name} - ${price}"
77

8+
// Test Product
9+
// const laptop = new Product('Laptop', 999.99)
10+
// const mouse = new Product('Mouse', 29.99)
11+
// console.log(laptop)
12+
// console.log(mouse)
13+
814
// 🐨 Create a ShoppingCart class with:
915
// - Field: items (Array<Product>)
1016
// - Constructor to initialize empty items array
1117
// - Method: addItem(product: Product) adds to items
1218
// - Method: getTotal() returns sum of all product prices
1319

14-
// Test your classes
15-
// const laptop = new Product('Laptop', 999.99)
16-
// const mouse = new Product('Mouse', 29.99)
20+
// Test ShoppingCart
1721
// const cart = new ShoppingCart()
1822
// cart.addItem(laptop)
1923
// cart.addItem(mouse)
2024
// console.log(cart.getTotal())
25+
// console.log(cart)
2126

22-
// 🐨 Export your classes so we can verify your work
23-
// 💰 Export the classes you created
27+
// export { Product, ShoppingCart }

exercises/01.classes/02.problem.private-fields-and-defaults/README.mdx

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,21 @@ JavaScript has native private fields using the `#` prefix. These fields are
99
truly private—they can only be accessed inside the class:
1010

1111
```ts
12-
class BankAccount {
13-
#balance: number = 0 // Truly private - not accessible outside the class
12+
class Counter {
13+
#count: number = 0 // Truly private - not accessible outside the class
1414

15-
deposit(amount: number) {
16-
this.#balance += amount
15+
increment() {
16+
this.#count++
17+
}
18+
19+
getValue() {
20+
return this.#count
1721
}
1822
}
1923

20-
const account = new BankAccount()
21-
account.#balance // ❌ Error! Private field not accessible
24+
const counter = new Counter()
25+
counter.increment()
26+
counter.#count // ❌ Error! Private field not accessible
2227
```
2328

2429
Private fields enable **encapsulation**—hiding internal implementation details
@@ -30,18 +35,20 @@ your code more maintainable.
3035
Constructors can use default parameter values to make some parameters optional:
3136

3237
```ts
33-
class User {
34-
name: string
35-
role: string
36-
37-
constructor(name: string, role: string = 'user') {
38-
this.name = name
39-
this.role = role
38+
class Car {
39+
make: string
40+
model: string
41+
year: number
42+
43+
constructor(make: string, model: string, year: number = 2024) {
44+
this.make = make
45+
this.model = model
46+
this.year = year
4047
}
4148
}
4249

43-
const user = new User('Alice') // role defaults to 'user'
44-
const admin = new User('Bob', 'admin') // role explicitly set
50+
const newCar = new Car('Toyota', 'Camry') // year defaults to 2024
51+
const oldCar = new Car('Ford', 'Mustang', 1965) // year explicitly set
4552
```
4653

4754
🐨 Open <InlineFile file="index.ts" /> and:

exercises/01.classes/02.problem.private-fields-and-defaults/index.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,34 @@
66
// - role: string (default: 'user')
77
// Initialize fields in the constructor
88

9+
// Test User
10+
// const user = new User('Alice', 'alice@example.com')
11+
// const admin = new User('Bob', 'bob@example.com', 'admin')
12+
// console.log(user)
13+
// console.log(admin)
14+
915
// 🐨 Create a BankAccount class with:
1016
// - accountNumber: string
1117
// - #balance: number (private field, default: 0)
1218
// - Method: deposit(amount: number)
1319
// - Method: getBalance() returns the balance
1420
// 💰 #balance is a private field - can only be accessed inside the class
1521

22+
// Test BankAccount
23+
// const account = new BankAccount('12345')
24+
// account.deposit(100)
25+
// console.log(account)
26+
// console.log(account.getBalance())
27+
1628
// 🐨 Create a Config class with optional default values:
1729
// - host: string (default: 'localhost')
1830
// - port: number (default: 3000)
1931
// - debug: boolean (default: false)
2032

21-
// Test
22-
// const user = new User('Alice', 'alice@example.com')
23-
// const admin = new User('Bob', 'bob@example.com', 'admin')
24-
// const account = new BankAccount('12345')
25-
// account.deposit(100)
33+
// Test Config
2634
// const config = new Config()
2735
// const customConfig = new Config('example.com', 8080, true)
36+
// console.log(config)
37+
// console.log(customConfig)
2838

29-
// 🐨 Export your classes so we can verify your work
30-
// 💰 Export the classes you created
39+
// export { User, BankAccount, Config }

exercises/02.interfaces-and-classes/01.problem.implementing-interfaces/index.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,19 @@
88
// - Constructor that takes cardNumber
99
// - Implement pay(amount: number) returns "Paid $${amount} with credit card ${cardNumber}"
1010

11+
// Test CreditCard
12+
// const creditCard = new CreditCard('1234-5678-9012-3456')
13+
// console.log(creditCard.pay(100))
14+
// console.log(creditCard)
15+
1116
// 🐨 Create a PayPal class that implements PaymentMethod:
1217
// - Field: email (string)
1318
// - Constructor that takes email
1419
// - Implement pay(amount: number) returns "Paid $${amount} with PayPal ${email}"
1520

16-
// Test your classes
17-
// const creditCard = new CreditCard('1234-5678-9012-3456')
21+
// Test PayPal
1822
// const paypal = new PayPal('user@example.com')
19-
// console.log(creditCard.pay(100))
2023
// console.log(paypal.pay(50))
24+
// console.log(paypal)
2125

22-
// 🐨 Export your classes so we can verify your work
23-
// 💰 Export the classes you created
26+
// export { CreditCard, PayPal }

exercises/02.interfaces-and-classes/02.problem.programming-to-abstractions/index.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,26 @@
88
// - Constructor that takes cardNumber
99
// - Implement pay(amount: number) returns "Paid $${amount} with credit card ${cardNumber}"
1010

11+
// Test CreditCard
12+
// const creditCard = new CreditCard('1234-5678-9012-3456')
13+
// console.log(creditCard)
14+
1115
// 🐨 Create a PayPal class implementing PaymentMethod:
1216
// - Field: email (string)
1317
// - Constructor that takes email
1418
// - Implement pay(amount: number) returns "Paid $${amount} with PayPal ${email}"
1519

20+
// Test PayPal
21+
// const paypal = new PayPal('user@example.com')
22+
// console.log(paypal)
23+
1624
// 🐨 Create a processPayment function:
1725
// - Parameters: method (PaymentMethod), amount (number)
1826
// - Returns: string
1927
// - Calls method.pay(amount)
2028

21-
// Test your code
22-
// const creditCard = new CreditCard('1234-5678-9012-3456')
23-
// const paypal = new PayPal('user@example.com')
29+
// Test processPayment
2430
// console.log(processPayment(creditCard, 100))
2531
// console.log(processPayment(paypal, 50))
2632

27-
// 🐨 Export your classes and function so we can verify your work
28-
// 💰 Export the classes and function you created
33+
// export { CreditCard, PayPal, processPayment }

exercises/03.inheritance/01.problem.extends/index.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,21 @@
99
// - Constructor that takes color and radius
1010
// - Call super(color) to initialize parent
1111

12+
// Test Circle
13+
// const circle = new Circle('red', 5)
14+
// console.log(circle.color) // ✅ Should work - inherited from Shape
15+
// console.log(circle.radius) // ✅ Should work - defined in Circle
16+
// console.log(circle)
17+
1218
// 🐨 Create a Rectangle class that extends Shape:
1319
// - Fields: width (number), height (number)
1420
// - Constructor that takes color, width, and height
1521
// - Call super(color) to initialize parent
1622

17-
// Test your classes
18-
// const circle = new Circle('red', 5)
23+
// Test Rectangle
1924
// const rectangle = new Rectangle('blue', 10, 20)
20-
// console.log(circle.color) // ✅ Should work - inherited from Shape
21-
// console.log(circle.radius) // ✅ Should work - defined in Circle
2225
// console.log(rectangle.color) // ✅ Should work - inherited from Shape
2326
// console.log(rectangle.width, rectangle.height) // ✅ Should work
27+
// console.log(rectangle)
2428

25-
// 🐨 Export your classes so we can verify your work
26-
// 💰 Export the classes you created
29+
// export { Shape, Circle, Rectangle }

exercises/03.inheritance/02.problem.method-overriding/index.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,19 @@
1010
// - Constructor that takes color and radius
1111
// - Override getArea() to return Math.PI * radius ** 2
1212

13+
// Test Circle
14+
// const circle = new Circle('red', 5)
15+
// console.log(circle.getArea()) // Should print ~78.54
16+
// console.log(circle)
17+
1318
// 🐨 Create a Rectangle class that extends Shape:
1419
// - Fields: width (number), height (number)
1520
// - Constructor that takes color, width, and height
1621
// - Override getArea() to return width * height
1722

18-
// Test your classes
19-
// const circle = new Circle('red', 5)
23+
// Test Rectangle
2024
// const rectangle = new Rectangle('blue', 10, 20)
21-
// console.log(circle.getArea()) // Should print ~78.54
2225
// console.log(rectangle.getArea()) // Should print 200
26+
// console.log(rectangle)
2327

24-
// 🐨 Export your classes so we can verify your work
25-
// 💰 Export the classes you created
28+
// export { Shape, Circle, Rectangle }

exercises/04.polymorphism/01.problem.substitutability/index.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,25 @@
88
// 🐨 Create an AudioFile class that extends MediaFile:
99
// - Override play() to return "Playing audio: {filename}"
1010

11+
// Test AudioFile
12+
// const audio = new AudioFile('song.mp3')
13+
// console.log(audio)
14+
1115
// 🐨 Create a VideoFile class that extends MediaFile:
1216
// - Override play() to return "Playing video: {filename}"
1317

18+
// Test VideoFile
19+
// const video = new VideoFile('movie.mp4')
20+
// console.log(video)
21+
1422
// 🐨 Create a MediaPlayer class with:
1523
// - Method: playFile(media: MediaFile) returns string
1624
// - Calls media.play() and returns the result
1725

18-
// Test polymorphism
19-
// const audio = new AudioFile('song.mp3')
20-
// const video = new VideoFile('movie.mp4')
26+
// Test MediaPlayer (polymorphism)
2127
// const player = new MediaPlayer()
2228
// console.log(player.playFile(audio)) // Should work - AudioFile is substitutable for MediaFile
2329
// console.log(player.playFile(video)) // Should work - VideoFile is substitutable for MediaFile
30+
// console.log(player)
2431

25-
// 🐨 Export your classes so we can verify your work
26-
// 💰 Export the classes you created
32+
// export { MediaFile, AudioFile, VideoFile, MediaPlayer }

exercises/05.composition-vs-inheritance/01.problem.when-to-use/index.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,30 @@
88
// - Extends Logger
99
// - Override log() to print "File Log: {message}"
1010

11+
// Test FileLogger
12+
// const fileLogger = new FileLogger()
13+
// fileLogger.log('File system initialized')
14+
// console.log(fileLogger)
15+
1116
// 🐨 Create a ConsoleLogger class using INHERITANCE (is-a):
1217
// - Extends Logger
1318
// - Override log() to print "Console Log: {message}"
1419

20+
// Test ConsoleLogger
21+
// const consoleLogger = new ConsoleLogger()
22+
// consoleLogger.log('Console ready')
23+
// console.log(consoleLogger)
24+
1525
// 🐨 Create an EmailService class using COMPOSITION (has-a):
1626
// - Field: #logger (Logger) - private field
1727
// - Constructor that takes a Logger
1828
// - Method: sendEmail(to: string, subject: string) returns void
1929
// - Uses this.#logger.log() to log the email action
2030
// - Prints "Sending email to {to}: {subject}"
2131

22-
// Test your code
23-
// const fileLogger = new FileLogger()
24-
// const consoleLogger = new ConsoleLogger()
32+
// Test EmailService
2533
// const emailService = new EmailService(fileLogger)
26-
// fileLogger.log('File system initialized')
27-
// consoleLogger.log('Console ready')
2834
// emailService.sendEmail('user@example.com', 'Welcome')
35+
// console.log(emailService)
2936

30-
// 🐨 Export your classes so we can verify your work
31-
// 💰 Export the classes you created
37+
// export { Logger, FileLogger, ConsoleLogger, EmailService }

0 commit comments

Comments
 (0)