/* Why do we need Java? It's no big deal to emulate objects, (without "private" encapsulation, which is a debatable advantage anyway). But what about object oriented programming? I wish to have two types of accounts: checking and savings. Checking accounts charge a fee when the balance falls below a miniumu. Savings accounts have a (tiny) interests rate that's applied to large deposits. But I still want to be able to treat all accounts generically. We need to think not just in terms of how easy/hard it is to write this program but also how easy it is to extend it in the future, in other words, in terms of the SCALABILITY of the language paradigm. */ #include #include #define GENERIC 0 #define CHECKING 1 #define SAVINGS 2 typedef struct accstruct * account; struct accstruct { int tag; double balance; char* name; union { double interest; int fee; // flat fee } extra; }; void inquiry(account A) { printf("%s has balance %.2f\n", A->name, A->balance); } void withdrawg(account A, double amt) { if (amt>0 && amtbalance) A->balance-=amt; } void depositg(account A, double amt) { if (amt>0) A->balance+=amt; } int moremoney(account A, account B) { return A->balance > B->balance; } account newaccount(char* n, double b) { account A = (account)malloc(sizeof(struct accstruct)); A->name=n; A->balance=b; A->tag=0; return A; } void bless(account A, int tag) // I bless { A->tag = tag; } account new_savings(char* n, double b, double i) { account A = newaccount(n,b); // call superclass constructor A->extra.interest = i; bless(A,SAVINGS); return A; } account new_checking(char* n, double b, int f) { account A = newaccount(n,b); // call superclass constructor A->extra.fee = f; bless(A,CHECKING); return A; } // need to "override" savings deposit and checking withdraw void withdraw_c(account A, double amt) { if (amt>0 && amtbalance) A->balance-=amt; if (A->balance < 500) A->balance -= A->extra.fee; } void deposit_s(account A, double amt) { if (amt>0) A->balance += amt; if (amt>10000) A->balance += amt*A->extra.interest; // interest < 0.0001 } // but now need to make sure the right version of withdraw/deposit is called. void withdraw(account A, double amt) { if (A->tag==CHECKING) withdraw_c(A,amt); else withdrawg(A,amt); } // set up dispatch vectors (use all of C's capabilities) typedef void (*banktrans)(account,double); banktrans ddispatch[3]; // = {&depositg, &depositg, &deposit_s}; void dispatchsetup() { ddispatch[0] = ddispatch[1]=&depositg; ddispatch[2] = &deposit_s; } void deposit(account A, double amt) { ddispatch[A->tag](A,amt); } int main() { dispatchsetup(); account myaccount = new_checking("prof",1000,5); account youraccount = new_savings("student",10000,0.001); withdraw(myaccount,900); // instead of myaccount.withdraw(900) deposit(youraccount,20000); // is this just a difference in syntax? // polymorphic code: account A[2] = {myaccount,youraccount}; int i=0; for(;i<2;i++) withdraw(A[i],10); // dynamic dispatch here inquiry(myaccount); inquiry(youraccount); return 0; }//main