@icarusmx/creta 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lessons/lesson6-interface-design.js +198 -129
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// LECCIÓN 6: El énfasis al diseñar los objetos debe estar en la definición de sus solicitudes e interfaces
|
|
4
|
-
// Enfoque práctico: Sistema
|
|
4
|
+
// Enfoque práctico: Sistema bancario con diseño interface-first y encapsulación
|
|
5
5
|
|
|
6
6
|
import { createInterface } from 'readline'
|
|
7
7
|
|
|
@@ -33,13 +33,13 @@ export class Lesson6InterfaceDesign {
|
|
|
33
33
|
|
|
34
34
|
async practicalExercise() {
|
|
35
35
|
console.clear()
|
|
36
|
-
console.log("🛠️ EJERCICIO PRÁCTICO: Sistema
|
|
36
|
+
console.log("🛠️ EJERCICIO PRÁCTICO: Sistema Bancario")
|
|
37
37
|
console.log("=" .repeat(50))
|
|
38
38
|
console.log("🎯 Objetivo: Diseñar interfaces ANTES de implementar")
|
|
39
|
-
console.log("\nVamos a crear un sistema donde:")
|
|
40
|
-
console.log("-
|
|
41
|
-
console.log("-
|
|
42
|
-
console.log("-
|
|
39
|
+
console.log("\nVamos a crear un sistema bancario donde:")
|
|
40
|
+
console.log("- BankAccount representa una cuenta con balance privado")
|
|
41
|
+
console.log("- Transaction registra movimientos entre cuentas")
|
|
42
|
+
console.log("- Bank gestiona múltiples cuentas y validaciones")
|
|
43
43
|
|
|
44
44
|
await this.waitForEnter("\nPresiona Enter para ver cómo diseñar las interfaces...")
|
|
45
45
|
|
|
@@ -54,21 +54,22 @@ export class Lesson6InterfaceDesign {
|
|
|
54
54
|
console.log("📋 PASO 1: Definir las Solicitudes")
|
|
55
55
|
console.log("=" .repeat(40))
|
|
56
56
|
console.log("Antes de escribir código, pensemos: ¿Qué solicitudes debe manejar cada objeto?")
|
|
57
|
-
console.log("\n
|
|
58
|
-
console.log(" -
|
|
59
|
-
console.log(" -
|
|
60
|
-
console.log(" -
|
|
61
|
-
console.log(" -
|
|
62
|
-
|
|
63
|
-
console.log("\n
|
|
64
|
-
console.log(" -
|
|
65
|
-
console.log(" -
|
|
66
|
-
console.log(" - Validar si
|
|
67
|
-
|
|
68
|
-
console.log("\n
|
|
69
|
-
console.log(" -
|
|
70
|
-
console.log(" -
|
|
71
|
-
console.log(" -
|
|
57
|
+
console.log("\n🏦 BankAccount debe poder:")
|
|
58
|
+
console.log(" - Consultar balance (sin exponer el dato interno)")
|
|
59
|
+
console.log(" - Recibir dinero (depósito)")
|
|
60
|
+
console.log(" - Enviar dinero (con validación interna)")
|
|
61
|
+
console.log(" - Proporcionar información de la cuenta")
|
|
62
|
+
|
|
63
|
+
console.log("\n📊 Transaction debe poder:")
|
|
64
|
+
console.log(" - Registrar origen, destino y monto")
|
|
65
|
+
console.log(" - Proporcionar detalles del movimiento")
|
|
66
|
+
console.log(" - Validar si la transacción es válida")
|
|
67
|
+
|
|
68
|
+
console.log("\n🏛️ Bank debe poder:")
|
|
69
|
+
console.log(" - Crear nuevas cuentas")
|
|
70
|
+
console.log(" - Procesar transferencias entre cuentas")
|
|
71
|
+
console.log(" - Validar operaciones antes de ejecutarlas")
|
|
72
|
+
console.log(" - Llevar registro de todas las transacciones")
|
|
72
73
|
|
|
73
74
|
await this.waitForEnter("\n✅ ¡Excelente! Ya definimos QUÉ debe hacer cada objeto. Presiona Enter para definir las interfaces...")
|
|
74
75
|
}
|
|
@@ -79,33 +80,36 @@ export class Lesson6InterfaceDesign {
|
|
|
79
80
|
console.log("=" .repeat(50))
|
|
80
81
|
console.log("Ahora especifiquemos CÓMO se solicitan estas operaciones:")
|
|
81
82
|
|
|
82
|
-
console.log("\n//
|
|
83
|
-
console.log("class
|
|
84
|
-
console.log("
|
|
85
|
-
console.log("
|
|
86
|
-
console.log("
|
|
87
|
-
console.log("
|
|
83
|
+
console.log("\n// BankAccount Interface")
|
|
84
|
+
console.log("class BankAccount {")
|
|
85
|
+
console.log(" constructor(accountNumber, ownerName, initialBalance) → BankAccount")
|
|
86
|
+
console.log(" getBalance() → number // ⚠️ ENCAPSULACIÓN: acceso controlado")
|
|
87
|
+
console.log(" getAccountInfo() → {number, owner, balance}")
|
|
88
|
+
console.log(" deposit(amount) → boolean")
|
|
89
|
+
console.log(" send(amount, targetAccount) → boolean // ⚠️ VALIDACIÓN interna")
|
|
88
90
|
console.log("}")
|
|
89
91
|
|
|
90
|
-
console.log("\n//
|
|
91
|
-
console.log("class
|
|
92
|
-
console.log(" constructor(
|
|
93
|
-
console.log("
|
|
94
|
-
console.log("
|
|
95
|
-
console.log(" isCompleted() → boolean")
|
|
92
|
+
console.log("\n// Transaction Interface")
|
|
93
|
+
console.log("class Transaction {")
|
|
94
|
+
console.log(" constructor(from, to, amount, timestamp) → Transaction")
|
|
95
|
+
console.log(" getDetails() → {from, to, amount, timestamp, status}")
|
|
96
|
+
console.log(" isValid() → boolean")
|
|
96
97
|
console.log("}")
|
|
97
98
|
|
|
98
|
-
console.log("\n//
|
|
99
|
-
console.log("class
|
|
100
|
-
console.log("
|
|
101
|
-
console.log("
|
|
102
|
-
console.log("
|
|
99
|
+
console.log("\n// Bank Interface")
|
|
100
|
+
console.log("class Bank {")
|
|
101
|
+
console.log(" createAccount(ownerName, initialBalance) → BankAccount")
|
|
102
|
+
console.log(" transfer(fromAccount, toAccount, amount) → Transaction")
|
|
103
|
+
console.log(" getAllTransactions() → Array<Transaction>")
|
|
104
|
+
console.log(" validateOperation(account, amount) → boolean")
|
|
103
105
|
console.log("}")
|
|
104
106
|
|
|
105
107
|
console.log("\n💡 Observa que cada operación especifica:")
|
|
106
|
-
console.log(" a) Nombre de la operación (
|
|
107
|
-
console.log(" b) Insumos necesarios (
|
|
108
|
-
console.log(" c) Valor que regresa (
|
|
108
|
+
console.log(" a) Nombre de la operación (getBalance, send, transfer, etc.)")
|
|
109
|
+
console.log(" b) Insumos necesarios (amount, targetAccount, etc.)")
|
|
110
|
+
console.log(" c) Valor que regresa (boolean, Transaction, etc.)")
|
|
111
|
+
console.log("\n🔒 Nota especial: getBalance() encapsula el acceso al estado interno")
|
|
112
|
+
console.log("🛡️ Nota especial: send() incluirá validación antes de ejecutar")
|
|
109
113
|
|
|
110
114
|
await this.waitForEnter("\n✅ Interfaces definidas. Presiona Enter para implementar...")
|
|
111
115
|
}
|
|
@@ -116,90 +120,126 @@ export class Lesson6InterfaceDesign {
|
|
|
116
120
|
console.log("=" .repeat(40))
|
|
117
121
|
console.log("Ahora que tenemos las interfaces claras, implementemos:")
|
|
118
122
|
|
|
119
|
-
console.log("\n// Implementación de
|
|
120
|
-
console.log(`class
|
|
121
|
-
constructor(
|
|
122
|
-
this.
|
|
123
|
-
this.
|
|
124
|
-
this
|
|
125
|
-
this.completed = false
|
|
123
|
+
console.log("\n// Implementación de BankAccount")
|
|
124
|
+
console.log(`class BankAccount {
|
|
125
|
+
constructor(accountNumber, ownerName, initialBalance) {
|
|
126
|
+
this.accountNumber = accountNumber
|
|
127
|
+
this.ownerName = ownerName
|
|
128
|
+
this.#balance = initialBalance // 🔒 PRIVADO: no se accede directamente
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
|
|
131
|
+
// 🔑 ENCAPSULACIÓN: método GET para acceder al balance
|
|
132
|
+
getBalance() {
|
|
133
|
+
return this.#balance
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getAccountInfo() {
|
|
129
137
|
return {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
completed: this.completed
|
|
138
|
+
number: this.accountNumber,
|
|
139
|
+
owner: this.ownerName,
|
|
140
|
+
balance: this.#balance // Controlamos qué se expone
|
|
134
141
|
}
|
|
135
142
|
}
|
|
136
143
|
|
|
137
|
-
|
|
138
|
-
|
|
144
|
+
deposit(amount) {
|
|
145
|
+
if (amount > 0) {
|
|
146
|
+
this.#balance += amount
|
|
147
|
+
return true
|
|
148
|
+
}
|
|
149
|
+
return false
|
|
139
150
|
}
|
|
140
151
|
|
|
141
|
-
|
|
142
|
-
|
|
152
|
+
// 🛡️ VALIDACIÓN: método SEND con lógica interna
|
|
153
|
+
send(amount, targetAccount) {
|
|
154
|
+
// Validación interna ANTES de ejecutar
|
|
155
|
+
if (amount > 0 && this.#balance >= amount) {
|
|
156
|
+
this.#balance -= amount
|
|
157
|
+
targetAccount.deposit(amount)
|
|
158
|
+
return true
|
|
159
|
+
}
|
|
160
|
+
return false // Fondos insuficientes o monto inválido
|
|
143
161
|
}
|
|
144
162
|
}`)
|
|
145
163
|
|
|
146
|
-
await this.waitForEnter("\nPresiona Enter para ver
|
|
164
|
+
await this.waitForEnter("\nPresiona Enter para ver Transaction...")
|
|
147
165
|
|
|
148
|
-
console.log("\n// Implementación de
|
|
149
|
-
console.log(`class
|
|
150
|
-
constructor() {
|
|
151
|
-
this.
|
|
166
|
+
console.log("\n// Implementación de Transaction")
|
|
167
|
+
console.log(`class Transaction {
|
|
168
|
+
constructor(fromAccount, toAccount, amount) {
|
|
169
|
+
this.fromAccount = fromAccount
|
|
170
|
+
this.toAccount = toAccount
|
|
171
|
+
this.amount = amount
|
|
172
|
+
this.timestamp = new Date()
|
|
173
|
+
this.status = 'pending'
|
|
152
174
|
}
|
|
153
175
|
|
|
154
|
-
|
|
155
|
-
|
|
176
|
+
getDetails() {
|
|
177
|
+
return {
|
|
178
|
+
from: this.fromAccount.accountNumber,
|
|
179
|
+
to: this.toAccount.accountNumber,
|
|
180
|
+
amount: this.amount,
|
|
181
|
+
timestamp: this.timestamp,
|
|
182
|
+
status: this.status
|
|
183
|
+
}
|
|
156
184
|
}
|
|
157
185
|
|
|
158
|
-
|
|
159
|
-
return
|
|
186
|
+
isValid() {
|
|
187
|
+
return this.amount > 0 &&
|
|
188
|
+
this.fromAccount.getBalance() >= this.amount
|
|
160
189
|
}
|
|
161
190
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.
|
|
166
|
-
return
|
|
191
|
+
execute() {
|
|
192
|
+
if (this.isValid()) {
|
|
193
|
+
const success = this.fromAccount.send(this.amount, this.toAccount)
|
|
194
|
+
this.status = success ? 'completed' : 'failed'
|
|
195
|
+
return success
|
|
167
196
|
}
|
|
197
|
+
this.status = 'failed'
|
|
168
198
|
return false
|
|
169
199
|
}
|
|
170
200
|
}`)
|
|
171
201
|
|
|
172
|
-
await this.waitForEnter("\nPresiona Enter para ver
|
|
202
|
+
await this.waitForEnter("\nPresiona Enter para ver Bank...")
|
|
173
203
|
|
|
174
|
-
console.log("\n// Implementación de
|
|
175
|
-
console.log(`class
|
|
176
|
-
constructor(
|
|
177
|
-
this.
|
|
178
|
-
this.
|
|
204
|
+
console.log("\n// Implementación de Bank")
|
|
205
|
+
console.log(`class Bank {
|
|
206
|
+
constructor() {
|
|
207
|
+
this.accounts = []
|
|
208
|
+
this.transactions = []
|
|
209
|
+
this.nextAccountNumber = 1000
|
|
179
210
|
}
|
|
180
211
|
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
212
|
+
createAccount(ownerName, initialBalance) {
|
|
213
|
+
const account = new BankAccount(
|
|
214
|
+
this.nextAccountNumber++,
|
|
215
|
+
ownerName,
|
|
216
|
+
initialBalance
|
|
217
|
+
)
|
|
218
|
+
this.accounts.push(account)
|
|
219
|
+
return account
|
|
185
220
|
}
|
|
186
221
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
222
|
+
transfer(fromAccount, toAccount, amount) {
|
|
223
|
+
const transaction = new Transaction(fromAccount, toAccount, amount)
|
|
190
224
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return true
|
|
225
|
+
// El Bank valida ANTES de ejecutar
|
|
226
|
+
if (this.validateOperation(fromAccount, amount)) {
|
|
227
|
+
const success = transaction.execute()
|
|
228
|
+
this.transactions.push(transaction)
|
|
229
|
+
return transaction
|
|
197
230
|
}
|
|
198
|
-
|
|
231
|
+
|
|
232
|
+
transaction.status = 'failed'
|
|
233
|
+
this.transactions.push(transaction)
|
|
234
|
+
return transaction
|
|
199
235
|
}
|
|
200
236
|
|
|
201
|
-
|
|
202
|
-
return
|
|
237
|
+
validateOperation(account, amount) {
|
|
238
|
+
return amount > 0 && account.getBalance() >= amount
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
getAllTransactions() {
|
|
242
|
+
return [...this.transactions]
|
|
203
243
|
}
|
|
204
244
|
}`)
|
|
205
245
|
|
|
@@ -212,63 +252,87 @@ export class Lesson6InterfaceDesign {
|
|
|
212
252
|
console.log("=" .repeat(45))
|
|
213
253
|
console.log("Veamos cómo los objetos colaboran usando sus interfaces:")
|
|
214
254
|
|
|
215
|
-
console.log("\n// Crear el sistema")
|
|
216
|
-
console.log("const
|
|
217
|
-
console.log("const
|
|
255
|
+
console.log("\n// Crear el sistema bancario")
|
|
256
|
+
console.log("const bank = new Bank()")
|
|
257
|
+
console.log("const cuenta1 = bank.createAccount('Ana García', 1000)")
|
|
258
|
+
console.log("const cuenta2 = bank.createAccount('Carlos López', 500)")
|
|
259
|
+
console.log("")
|
|
260
|
+
console.log("// 🔑 ENCAPSULACIÓN: Solo podemos acceder al balance via getBalance()")
|
|
261
|
+
console.log("console.log('Balance Ana:', cuenta1.getBalance()) // 1000")
|
|
262
|
+
console.log("console.log('Balance Carlos:', cuenta2.getBalance()) // 500")
|
|
218
263
|
console.log("")
|
|
219
|
-
console.log("//
|
|
220
|
-
console.log("const
|
|
221
|
-
console.log("
|
|
264
|
+
console.log("// 🛡️ VALIDACIÓN: send() verifica internamente antes de ejecutar")
|
|
265
|
+
console.log("const exitoso = cuenta1.send(300, cuenta2) // ✅ Tiene fondos")
|
|
266
|
+
console.log("console.log('Transferencia exitosa:', exitoso) // true")
|
|
222
267
|
console.log("")
|
|
223
|
-
console.log("
|
|
224
|
-
console.log("
|
|
225
|
-
console.log("const allTasks = manager.getAllTasks()")
|
|
268
|
+
console.log("const fallido = cuenta1.send(1500, cuenta2) // ❌ Fondos insuficientes")
|
|
269
|
+
console.log("console.log('Transferencia fallida:', fallido) // false")
|
|
226
270
|
console.log("")
|
|
227
|
-
console.log("
|
|
228
|
-
console.log("
|
|
229
|
-
console.log("
|
|
230
|
-
console.log("})")
|
|
271
|
+
console.log("// El estado interno se mantiene íntegro")
|
|
272
|
+
console.log("console.log('Balance final Ana:', cuenta1.getBalance()) // 700")
|
|
273
|
+
console.log("console.log('Balance final Carlos:', cuenta2.getBalance()) // 800")
|
|
231
274
|
|
|
232
275
|
console.log("\n🎯 Resultado esperado:")
|
|
233
|
-
console.log("
|
|
234
|
-
console.log("
|
|
276
|
+
console.log("Balance Ana: 1000")
|
|
277
|
+
console.log("Balance Carlos: 500")
|
|
278
|
+
console.log("Transferencia exitosa: true")
|
|
279
|
+
console.log("Transferencia fallida: false")
|
|
280
|
+
console.log("Balance final Ana: 700")
|
|
281
|
+
console.log("Balance final Carlos: 800")
|
|
235
282
|
|
|
236
283
|
await this.waitForEnter("\nPresiona Enter para ver los beneficios de este enfoque...")
|
|
237
284
|
|
|
238
285
|
console.clear()
|
|
239
|
-
console.log("🌟 BENEFICIOS DEL DISEÑO INTERFACE-FIRST")
|
|
240
|
-
console.log("=" .repeat(
|
|
241
|
-
console.log("1.
|
|
242
|
-
console.log("2.
|
|
243
|
-
console.log("3.
|
|
244
|
-
console.log("4.
|
|
245
|
-
console.log("5.
|
|
286
|
+
console.log("🌟 BENEFICIOS DEL DISEÑO INTERFACE-FIRST EN SISTEMAS BANCARIOS")
|
|
287
|
+
console.log("=" .repeat(60))
|
|
288
|
+
console.log("1. 🔒 Encapsulación: El balance está protegido, solo accesible via getBalance()")
|
|
289
|
+
console.log("2. 🛡️ Validación: send() incluye lógica de negocio interna")
|
|
290
|
+
console.log("3. 🎯 Claridad: Cada objeto tiene responsabilidades financieras bien definidas")
|
|
291
|
+
console.log("4. 🔗 Colaboración: Los objetos saben exactamente cómo solicitar operaciones")
|
|
292
|
+
console.log("5. 🧪 Testeable: Podemos simular cuentas y transacciones fácilmente")
|
|
293
|
+
console.log("6. 📚 Mantenible: Las interfaces documentan el contrato bancario")
|
|
246
294
|
|
|
247
295
|
console.log("\n💡 Ejemplo de extensibilidad:")
|
|
248
|
-
console.log("// Podemos
|
|
249
|
-
console.log("class
|
|
250
|
-
console.log("
|
|
251
|
-
console.log("
|
|
252
|
-
console.log("
|
|
296
|
+
console.log("// Podemos crear diferentes tipos de cuenta sin cambiar Bank")
|
|
297
|
+
console.log("class SavingsAccount extends BankAccount {")
|
|
298
|
+
console.log(" getBalance() {")
|
|
299
|
+
console.log(" return super.getBalance() + this.calculateInterest()")
|
|
300
|
+
console.log(" }")
|
|
301
|
+
console.log("}")
|
|
302
|
+
console.log("")
|
|
303
|
+
console.log("class CreditAccount extends BankAccount {")
|
|
304
|
+
console.log(" send(amount, target) {")
|
|
305
|
+
console.log(" // Permite sobregiro hasta el límite de crédito")
|
|
306
|
+
console.log(" if (amount > 0 && (this.getBalance() + this.creditLimit) >= amount) {")
|
|
307
|
+
console.log(" // ... lógica específica")
|
|
308
|
+
console.log(" }")
|
|
309
|
+
console.log(" }")
|
|
253
310
|
console.log("}")
|
|
254
311
|
console.log("")
|
|
255
|
-
console.log("//
|
|
256
|
-
console.log("const
|
|
257
|
-
console.log("const
|
|
312
|
+
console.log("// Bank sigue funcionando igual con cualquier tipo de cuenta!")
|
|
313
|
+
console.log("const savingsAcc = new SavingsAccount(123, 'María', 1000)")
|
|
314
|
+
console.log("const creditAcc = new CreditAccount(456, 'Juan', 500, 2000) // límite crédito")
|
|
315
|
+
console.log("bank.transfer(savingsAcc, creditAcc, 300) // ¡Funciona!")
|
|
258
316
|
|
|
259
317
|
await this.waitForEnter("\nPresiona Enter para continuar con la conclusión...")
|
|
260
318
|
}
|
|
261
319
|
|
|
262
320
|
async conclusion() {
|
|
263
321
|
console.clear()
|
|
264
|
-
console.log("🎓 CONCLUSIÓN: Diseño basado en Interfaces")
|
|
265
|
-
console.log("=" .repeat(
|
|
322
|
+
console.log("🎓 CONCLUSIÓN: Diseño basado en Interfaces (Sistema Bancario)")
|
|
323
|
+
console.log("=" .repeat(55))
|
|
266
324
|
console.log("🎯 Hemos demostrado que:")
|
|
267
325
|
console.log("\n1. El ÉNFASIS debe estar en definir QUÉ solicitudes maneja cada objeto")
|
|
268
326
|
console.log("2. Las INTERFACES especifican cómo hacer estas solicitudes")
|
|
269
327
|
console.log("3. La IMPLEMENTACIÓN viene después, siguiendo el contrato")
|
|
270
328
|
console.log("4. Los objetos COLABORAN a través de estas interfaces bien definidas")
|
|
271
329
|
|
|
330
|
+
console.log("\n🔑 Lecciones específicas del ejemplo bancario:")
|
|
331
|
+
console.log("• ENCAPSULACIÓN: getBalance() protege el acceso al estado interno")
|
|
332
|
+
console.log("• VALIDACIÓN: send() ejecuta lógica de negocio antes de operar")
|
|
333
|
+
console.log("• RESPONSABILIDAD: Cada objeto maneja su propia integridad")
|
|
334
|
+
console.log("• COLABORACIÓN: Bank, BankAccount y Transaction trabajan juntos")
|
|
335
|
+
|
|
272
336
|
console.log("\n📚 Conexión con lecciones anteriores:")
|
|
273
337
|
console.log("• Lección 2: Los objetos interactúan a través de solicitudes ✓")
|
|
274
338
|
console.log("• Lección 3: Las solicitudes son la única forma de ejecutar operaciones ✓")
|
|
@@ -280,12 +344,17 @@ export class Lesson6InterfaceDesign {
|
|
|
280
344
|
console.log("Practica este enfoque en tus propios proyectos:")
|
|
281
345
|
console.log("1. Define primero QUÉ debe hacer cada objeto")
|
|
282
346
|
console.log("2. Especifica las interfaces (firmas de operación)")
|
|
283
|
-
console.log("3.
|
|
284
|
-
console.log("4.
|
|
347
|
+
console.log("3. Incluye validaciones internas en tus métodos")
|
|
348
|
+
console.log("4. Encapsula el estado, expón solo lo necesario")
|
|
349
|
+
console.log("5. Haz que los objetos colaboren a través de solicitudes")
|
|
285
350
|
|
|
286
351
|
console.log("\n💭 Reflexión final:")
|
|
287
|
-
console.log("¿
|
|
288
|
-
console.log("
|
|
352
|
+
console.log("En el mundo real, ¿cómo te asegurarías de que tu cuenta bancaria")
|
|
353
|
+
console.log("esté protegida y que solo se ejecuten operaciones válidas?")
|
|
354
|
+
console.log("¡Exactamente como lo hicimos aquí: interfaces bien definidas!")
|
|
355
|
+
|
|
356
|
+
console.log("\n🏆 ¡Has completado el ejemplo más importante del diseño orientado a objetos!")
|
|
357
|
+
console.log("Ahora entiendes por qué el ÉNFASIS debe estar en las interfaces.")
|
|
289
358
|
|
|
290
359
|
await this.waitForEnter("\n✨ ¡Lección 6 completada! Presiona Enter para salir...")
|
|
291
360
|
}
|