Class Diagram: A graphical model representing conceptual objects and their relationships
Two Types of Relationships:
- Inheritance:
- Instance Level: Child objects are special kinds of a parent object (is-a relationship)
- Class Level: Child classes are sub classes of a parent class
- Wrong: A child object is contained in a parent object (why?)
- Example 1:
- Employee, FullTimer, and PartTimer
- Account, Checking, and Savings
- Encapsulation Principle Revisit:
- private data for parent class must be changed into protected one
- behavioral members must be changed into virtual if child class needs to change their implementation.
- Abstract operation: operation in a parent class that has no implementation (function body). Abstract operations have to be implemented in child classes
- Abstract class: A parent class that has one or more abstract operations
- Interface: an abstract class that has nothing but abstract operations.
- The purpose of abstract classes and interfaces is to set up a programming contract for all all sub classes to observe
- Association --any other kinds of relationships if they are related, including containment (has-a relation), assignment, correspondence, etc
- Cardinality or multiplicity: quantify how one object is associated with how many other objects
- Example: Customer and Account
- Navigability:
- qualify whether one object commands or asks other objects to perform their operations (e.g.: Pilot --> Airplane)
- qualify whether one object refers to or contains other objects as a part of its data members (e.g., Order --> Product)
Implementation: Programming Inheritance and Associations
- Inheritance: if A is a sub class of B: class B {//} and class A:B {//} . Examples: Parttimer : Employee {//} to show that Parttimer is a sub class of Employee; Savings:Account {//}; Checking:Account {//}
- Associations:
- Navigability
- A --> B: Create B's object(s) inside A as instance variables
- A -- B: Create B's object(s) inside A as instances variables and create A's object(s) inside B as instance variables
- Cardinality:
- If maximum cardinality is 1, create a single object as instance variable
- If maximum cardinality is greater than 1 and fixed, create an array of objects as an instance variable
- If maximum cardinality is greater than 1 and not fixed, create a list of objects as an instance variable
- A --> B: class A has one (cardinality on B size is one) or more (cardinality on B side is many) B's instances as attributes
- A -- B class A has has one (cardinality on B size is one) or more (cardinality on B side is many) B's instances as attributes, and Class B has one (cardinality on A size is one) or more (cardinality on A side is many) A's instances as attributes
- Example: Customer -- Order --> Product
Advanced Coding Concepts on Inheritance: virtual operations, abstract operations, abstract classes, and interface

public abstract class Account
{
//if each account belongs to upt to a certain number of customers
//protected Customer[] customers;
//if each account belongs to an unknown numbers of customers
//protected List customers;
//if each account belongs to one customer
protected Customer customer;
protected int acctNo;
protected double balance;
//protected string acctType;
protected DateTime openDate;
public Account()
{
acctNo = 0;
balance = 0;
openDate = DateTime.Now;
//if each account belongs to upt to 5 customers
//customers = new Customer[5];
//if each account belongs to an unknown numbers of customers
//customers = new List();
//if each account belongs to one customer
customer = new Customer();
}
public Account(int newAcctNo, double newBalance, DateTime newOpenDate, Customer cust)
{
acctNo = newAcctNo;
balance = newBalance;
openDate = newOpenDate;
customer = cust;
}
public virtual void Credit(double amt)
{
balance = balance + amt;
}
public virtual void Debit(double amt)
{
if (balance < amt)
throw new Exception("insufficient fund");
else
balance = balance - amt;
}
public double GetBalace()
{
return balance;
}
public abstract double ComputeInterest();
}
public class Customer
{
private List<Account> accounts;
public Customer()
{
accounts = new List<Account>();
}
}
public class CheckingAccount : Account
{
private List<SavingsAccount> associtedSavings;
private int checksAllowed;
public CheckingAccount():base()
{
associtedSavings = new List<SavingsAccount>();
checksAllowed = 90;
}
public override double ComputeInterest()
{
//throw new NotImplementedException();
return 0;
}
}
public class SavingsAccount : Account
{
private CheckingAccount primaryChecking;
private double interestRate;
private DateTime validFrom;
private DateTime validUtil;
public override double ComputeInterest()
{
//throw new NotImplementedException();
if (validUtil > DateTime.Now)
{
TimeSpan ts = DateTime.Now - validFrom;
int years = ts.Days / 365;
return interestRate * balance * years;
}
else
{
TimeSpan ts = validUtil - validFrom;
int years = ts.Days / 365;
return interestRate * balance * years;
}
}
public SavingsAccount():base()
{
primaryChecking = new CheckingAccount();
interestRate = 0;
validUtil = DateTime.Now;
}
}
public class CD : Account
{
private double interestRate;
private DateTime maturity;
public CD():base()
{
interestRate = 0;
maturity = DateTime.Now;
}
public override double ComputeInterest()
{
//throw new NotImplementedException();
if (DateTime.Now < maturity)
return 0;
else
{
TimeSpan ts = maturity - openDate;
int years = ts.Days/365;
return balance * Math.Pow(1 + interestRate, years);
}
}
public override void Debit(double amt)
{
if (DateTime.Now < maturity)
throw new Exception("not matured yet");
else
base.Debit(amt);
}
}
Homework:
- Reading: Chapter 6 of LIU (2020)
- Exercises: Correctness Questions: online; Hands-on Questions: Question 9 of Chapter 6
|