Object Oriented Programming (OOP) Imperative Programming
Total Page:16
File Type:pdf, Size:1020Kb
Object Oriented Programming (OOP) IIIA o New programming paradigm o Actions Æ Objects o Objects Å Actions o Object-oriented = Objects + Classes + Inheritance TAPIA 2005-2006 Imperative programming IIIA o OOP (Object-Oriented Programming) related o Local state, delegation, inheritance o History (Norvig,465): Algol 60 Æ SIMULA o Lisp extensions: o Smalltalk (69) o Flavors (79) o New Flavors (81) o Common Loops (88) o CLOS (91): standard TAPIA 2005-2006 History IIIA Dahl 1966 Algol60 Simula Classes single inheritance Nygaard LISP world Kay 1969 Smalltalk Goldberg Ingalls Steele 1976 LAMBDA Cannon 1979 Flavors multiple inheritance method combination Weinreb Symbolics 1981 New Flavors generic functions Xerox 1982 CommonLoops multimethods AT&T 1986 C++ Bell labs Meyer 1988 Oaklisp Eiffel Lang 1988 Perlmutter CLOS Steele 1991 JAVA TAPIA 2005-2006 AOP vs. OOP (Shoham) IIIA OOP AOP Basic unit Object (passive) Agent (active) State without restriction belief, commitment, competence, preferences, … Computation Message passing, methods Message passing, methods Type of messages without restriction Inform, request, offer, promise, reject, … Message no Honesty, consistency, rationality, restrictions … TAPIA 2005-2006 Nomenclature IIIA o Object: encapsulated local state and behavior o Class: describes similar objects with the same behavior and structure. o Instance: object belonging to a class. o Class Variable: variable shared by all the members of a class. o Instance Variable: encapsulated variable of an object. o Generic Function: its behavior depends on the types or classes of the arguments. TAPIA 2005-2006 Nomenclature IIIA o Message: Action name. Equivalent to a generic function. o Method: Specialization of a generic function. o Delegation: an object passes a task to another object. o Multimethod: method with more than one argument o Inheritance: to define new classes that are a specialization of a more general one. o Multiple inheritance: from more than one father class. TAPIA 2005-2006 Object-Oriented Style IIIA o Example: Bank account class o Local state and functions o Instance variables: balance, interest rate o Messages and methods: withdraw, deposit, balance, name, interest o It is not possible to manipulate the variables in a closure using CommonLisp. o INSPECT is implementation dependent TAPIA 2005-2006 Object-Oriented Style IIIA (defun new-account (name &optional (balance 0.00) (interest-rate .06)) “new account with the following messages:" #'(lambda (message) (case message (withdraw #'(lambda (amt) (if (<= amt balance) (decf balance amt) 'insufficient-funds))) (deposit #'(lambda (amt) (incf balance amt))) (balance #'(lambda () balance)) (name #'(lambda () name)) (interest #'(lambda () (incf balance (* interest-rate balance))))))) TAPIA 2005-2006 SEND IIIA o Send function (Flavors) implements the control of objects. (defun get-method (object message) “Returns the method for the given message" (funcall object message)) (defun send (object message &rest args) “Applies the method for the message with the arguments” (apply (get-method object message) args)) TAPIA 2005-2006 SEND IIIA o Execution examples > (setf acct (new-account "J. Random Customer" 1000.00)) #<CLOSURE 23652465> > (send acct 'withdraw 500.00) Æ 500.0 > (send acct 'deposit 123.45) Æ 623.45 > (send acct 'name) Æ "J. Random Customer" > (send acct 'balance) Æ 623.45 TAPIA 2005-2006 Generic functions IIIA o The syntax of send is not useful. We are interested in expressions of the following type: o (mapcar 'balance accounts) o Using messages: o (mapcar #'(lambda (acct) (send acct 'balance)) accounts) o Generic functions will find the correct method of an object, specialized on a message type. o (defun withdraw (object &rest args) “withdraw is a generic function over objects." (apply (get-method object 'withdraw) args)) o We can write: o (withdraw acct x) o Instead of: o (send acct 'withdraw x) TAPIA 2005-2006 Classes IIIA o Using Macros o Easier read and write object-oriented code o Create a new class o Methods o Generic functions for each message o Class variables o Instance variables TAPIA 2005-2006 Classes IIIA (define-class account (name &optional (balance 0)) ((interest-rate .06)) (withdraw (amt) (if (<= amt balance (decf balance amt) 'insufficient-funds)) (deposit (amt) (incf balance amt)) (balance () balance) (name () name) (interest () (incf balance (* interest-rate balance)))) TAPIA 2005-2006 Classes IIIA (defmacro define-class (class inst-vars class-vars &body methods) “class definition." `(let ,class-vars (mapcar #'ensure-generic-fn ' ,(mapcar #'first methods)) (defun ,class ,inst-vars #'(lambda (message) (case message ,@(mapcar #'make-clause methods)))))) (defun make-clause (clause) "Translate a message from define-class into a case clause." `(,(first clause) #'(lambda ,(second clause) ,@(rest (rest clause))))) TAPIA 2005-2006 Classes II IIIA (defun ensure-generic-fn (message) “defines a generic function." (unless (or (generic-fn-p message) (eq message ‘otherwise)) (let ((fn #'(lambda (object &rest args) (apply (get-method object message) args)))) (setf (symbol-function message) fn) (setf (get message 'generic-fn) fn)))) (defun generic-fn-p (fn-name) “is fn-name a function?" (and (fboundp fn-name) (eq (get fn-name 'generic-fn) (symbol-function fn-name)))) TAPIA 2005-2006 Classes II IIIA (define-class account (name &optional (balance 0)) ((interest-rate .06)) (withdraw (amt) (if (<= amt balance (decf balance amt) 'insufficient-funds)) (deposit (amt) (incf balance amt)) (balance () balance) (name () name) (interest () (incf balance (* interest-rate balance)))) TAPIA 2005-2006 Classes III IIIA o Macro expansion: (LET ((INTEREST-RATE 0.06)) (MAPCAR #'ENSURE-GENERIC-FN '(WITHDRAW DEPOSIT BALANCE NAME INTEREST)) (DEFUN ACCOUNT (NAME &OPTIONAL (BALANCE 0.0)) #'(LAMBDA (MESSAGE) (CASE MESSAGE (WITHDRAW #'(LAMBDA (AMT) (IF (<= AMT BALANCE) (DECF BALANCE AMT) 'INSUFFICIENT-FUNDS))) (DEPOSIT #'(LAMBDA (AMT) (INCF BALANCE AMT))) (BALANCE #'(LAMBDA NIL BALANCE)) (NAME #'(LAMBDA NIL NAME)) (INTEREST #'(LAMBDA NIL (INCF BALANCE (* INTEREST-RATE BALANCE)))))))) TAPIA 2005-2006 Classes III IIIA o Using the new objects: o > (setf acct2 (account "A. User" 2000.00)) #<CLOSURE 24003064> o > (deposit acct2 42.00) -> 2042.0 o > (interest acct2) -> 2164.52 o > (balance acct2) -> 2164.52 Previous !!! o > (balance acct) -> 623.45 object TAPIA 2005-2006 Delegation I IIIA o Account with password: (define-class password-account (password acct) () (change-password (pass new-pass) (if (equal pass password) (setf password new-pass) 'wrong-password)) (otherwise (pass &rest args) (if (equal pass password) (apply message acct args) 'wrong-password))) TAPIA 2005-2006 Delegation I IIIA o Details of the define-class macro: message and otherwise. > (setf acct3 (password-account "secret" acct2)) #<CLOSURE 33427277> > (balance acct3 "secret") -> 2164.52 > (withdraw acct3 "guess" 2000.00) -> WRONG-PASSWORD > (withdraw acct3 "secret" 2000.00) -> 164.52 TAPIA 2005-2006 Delegation II IIIA o The same technique for “limited” accounts: (define-class limited-account (limit acct) () (withdraw (amt) (if (> amt limit) 'over-limit (withdraw acct amt))) (otherwise (&rest args) (apply message acct args))) TAPIA 2005-2006 Delegation II IIIA o > (setf acct4 (password-account "pass" (limited-account 100.00 (account "A. Thrifty Spender" 500.00)))) #<CLOSURE 34136775> o > (withdraw acct4 "pass" 200.00) Æ OVER-LIMIT o > (withdraw acct4 "pass" 20.00) Æ 480.0 o > (withdraw acct4 "guess" 20.00) WRONG-PASSWORD TAPIA 2005-2006 Delegation III IIIA o Each class implements a different withdraw method. Sending the message withdraw to the object acct4 : 1. password-account method validates the password. 2. If correct, sends the message withdraw to the limited-account object. 3. If under the limit, sends the message withdraw to the account object. o Notice the differences with the procedural version (defun withdraw (acct amt &optional pass) (cond ((and (typep acct 'password-account) (not (equal pass (account-password acct)))) 'wrong-password) ((and (typep acct 'limited-account) (> amt (account-limit account))) 'over-limit) ((> amt balance) 'insufficient-funds) (t (decf balance amt)))) TAPIA 2005-2006 Inheritance I IIIA o Classes are hierarchically organized. It is necessary to make explicit this hierarchy. o Lisp structures implement inheritance: (defstruct (limited-account (:include account)) limit) o The same for classes: (define-class limited-account account (limit) () (withdraw (amt) (if (>amt limit) 'over-limit (call-next-method))) TAPIA 2005-2006 Inheritance II IIIA o Multiple inheritance : (define-class limited-account-with-password (password-account limited-account)) o Union of the functionalities belonging to the two classes. o No new variable or methods. TAPIA 2005-2006 History IIIA Dahl 1966 Algol60 Simula Classes single inheritance Nygaard LISP world Kay 1969 Smalltalk Goldberg Ingalls Steele 1976 LAMBDA Cannon 1979 Flavors multiple inheritance method combination Weinreb Symbolics 1981 New Flavors generic functionsCommon Lisp Object System Xerox 1982 CommonLoops multimethods AT&T 1986 C++ Bell labs Meyer 1988 Oaklisp Eiffel Lang 1988 Perlmutter CLOS Steele 1991 JAVA TAPIA 2005-2006 CLOS: defclass IIIA Our System CLOS define-class defclass methods in class defmethod class-name make-instance call-next-method call-next-method ensure-generic-fn ensure-generic-function o Definition of: o Classes: defclass o Methods: delmethod o Instances: make-instance. o Syntax of class definition: (defclass class-name (superclass...)