Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 101 additions & 0 deletions Lecture 05/Typescript/LSP/LSPFollowed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// 1. DepositOnlyAccount interface: only allows deposits
interface DepositOnlyAccount {
deposit(amount: number): void
}

// 2. WithdrawableAccount interface: allows deposits and withdrawals
interface WithdrawableAccount extends DepositOnlyAccount {
withdraw(amount: number): void
}

class SavingAccount implements WithdrawableAccount {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Savings Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
if (this.balance >= amount) {
this.balance -= amount
console.log(`Withdrawn: ${amount} from Savings Account. New Balance: ${this.balance}`)
} else {
console.log("Insufficient funds in Savings Account!")
}
}
}

class CurrentAccount implements WithdrawableAccount {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Current Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
if (this.balance >= amount) {
this.balance -= amount
console.log(`Withdrawn: ${amount} from Current Account. New Balance: ${this.balance}`)
} else {
console.log("Insufficient funds in Current Account!")
}
}
}

class FixedTermAccount implements DepositOnlyAccount {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Fixed Term Account. New Balance: ${this.balance}`)
}
}

class BankClient {
private withdrawableAccounts: WithdrawableAccount[]
private depositOnlyAccounts: DepositOnlyAccount[]

constructor(
withdrawableAccounts: WithdrawableAccount[],
depositOnlyAccounts: DepositOnlyAccount[]
) {
this.withdrawableAccounts = withdrawableAccounts
this.depositOnlyAccounts = depositOnlyAccounts
}

processTransactions(): void {
for (const acc of this.withdrawableAccounts) {
acc.deposit(1000)
acc.withdraw(500)
}

for (const acc of this.depositOnlyAccounts) {
acc.deposit(5000)
}
}
}

function main(): void {
const withdrawableAccounts: WithdrawableAccount[] = [
new SavingAccount(),
new CurrentAccount()
]

const depositOnlyAccounts: DepositOnlyAccount[] = [
new FixedTermAccount()
]

const client = new BankClient(withdrawableAccounts, depositOnlyAccounts)
client.processTransactions()
}

main()

/**
* If a .ts file has no imports or exports, TypeScript treats it as a global script.
* Adding `export {}` marks the file as a module and prevents
* "Duplicate identifier 'SavingAccount'" errors.
*/
export {}
98 changes: 98 additions & 0 deletions Lecture 05/Typescript/LSP/LSPFollowedWrongly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Account interface
interface Account {
deposit(amount: number): void
withdraw(amount: number): void
}

class SavingAccount implements Account {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Savings Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
if (this.balance >= amount) {
this.balance -= amount
console.log(`Withdrawn: ${amount} from Savings Account. New Balance: ${this.balance}`)
} else {
console.log("Insufficient funds in Savings Account!")
}
}
}

class CurrentAccount implements Account {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Current Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
if (this.balance >= amount) {
this.balance -= amount
console.log(`Withdrawn: ${amount} from Current Account. New Balance: ${this.balance}`)
} else {
console.log("Insufficient funds in Current Account!")
}
}
}

class FixedTermAccount implements Account {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Fixed Term Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
throw new Error("Withdrawal not allowed in Fixed Term Account!")
}
}

class BankClient {
private accounts: Account[]

constructor(accounts: Account[]) {
this.accounts = accounts
}

processTransactions(): void {
for (const acc of this.accounts) {
acc.deposit(1000)

// Explicit type checking instead of true substitutability
if (acc instanceof FixedTermAccount) {
console.log("Skipping withdrawal for Fixed Term Account.")
} else {
try {
acc.withdraw(500)
} catch (e: any) {
console.log(`Exception: ${e.message}`)
}
}
}
}
}

function main(): void {
const accounts: Account[] = []
accounts.push(new SavingAccount())
accounts.push(new CurrentAccount())
accounts.push(new FixedTermAccount())

const client = new BankClient(accounts)
client.processTransactions()
}

main()

/**
* If a .ts file has no imports or exports, TypeScript treats it as a global script.
* Adding `export {}` marks the file as a module and prevents
* "Duplicate identifier 'SavingAccount'" errors.
*/
export {}
95 changes: 95 additions & 0 deletions Lecture 05/Typescript/LSP/LSPViolated.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Account interface
interface Account {
deposit(amount: number): void
withdraw(amount: number): void
}

class SavingAccount implements Account {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Savings Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
if (this.balance >= amount) {
this.balance -= amount
console.log(`Withdrawn: ${amount} from Savings Account. New Balance: ${this.balance}`)
} else {
console.log("Insufficient funds in Savings Account!")
}
}
}

class CurrentAccount implements Account {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Current Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
if (this.balance >= amount) {
this.balance -= amount
console.log(`Withdrawn: ${amount} from Current Account. New Balance: ${this.balance}`)
} else {
console.log("Insufficient funds in Current Account!")
}
}
}

class FixedTermAccount implements Account {
private balance: number = 0

deposit(amount: number): void {
this.balance += amount
console.log(`Deposited: ${amount} in Fixed Term Account. New Balance: ${this.balance}`)
}

withdraw(amount: number): void {
throw new Error("Withdrawal not allowed in Fixed Term Account!")
}
}

class BankClient {
private accounts: Account[]

constructor(accounts: Account[]) {
this.accounts = accounts
}

processTransactions(): void {
for (const acc of this.accounts) {
acc.deposit(1000)

// LSP violation: assuming all accounts support withdrawal
try {
acc.withdraw(500)
} catch (e: any) {
console.log(`Exception: ${e.message}`)
}
}
}
}

// Equivalent of Java main
function main(): void {
const accounts: Account[] = []
accounts.push(new SavingAccount())
accounts.push(new CurrentAccount())
accounts.push(new FixedTermAccount())

const client = new BankClient(accounts)
client.processTransactions()
}

main()

/**
* If a .ts file has no imports or exports, TypeScript treats it as a global script.
* Adding `export {}` marks the file as a module and prevents
* "Duplicate identifier 'SavingAccount'" errors.
*/
export {}
Loading