C311 script11.txt -- 4/8/97 --- OBJECT-ORIENTED PROGRAMMING --- REVIEW OF SOME TERMINOLOGY CLASS: a prototype for making an INSTANCE via INSTANTIATION (using the 'new' operation of C++ or Java) +++ METHOD: a procedure belonging to a class A.k.a. MEMBER FUNCTION in C++ +++ CLASS VARIABLE: binding belongs to the class Java, C++: static variables +++ INSTANCE VARIABLE: new binding created for each instance of the class Java: non-static variables belonging to a class +++ ELEMENTS of a class: its methods and variables (class and instance) A.k.a. class MEMBERS in C++ --- TYPE: a collection of objects related by some property Informally a set, e.g. integers, strings Procedure and method types specify the types of the arguments and result. In the context of OOP (object-oriented programming), classes and interfaces also are types. +++ INTERFACE or SIGNATURE: the type of an ADT (or class) Contains the names and types of all procedures (methods) of the ADT (class) Java: also may include final variables (constants) +++ METHOD OVERLOADING: more than one method in a class with the same name (and, in some systems, a different type) --- POLYMORPHISM: having more than one type (literally: having many forms) Three types of polymorphism: ad hoc, parametric, and bounded +++ AD HOC POLYMORPHISM: behavior depends on the actual type E.g. overloading +++ PARAMETRIC POLYMORPHISM: behavior is the same for all objects E.g. In scheme cons takes arguments of any type, and does the same thing regardless of their type. +++ BOUNDED POLYMORPHISM: parametric, but limited to subtypes of a given type Used extensively in OOP --- SUBTYPING: A is a SUBTYPE of B (and B is a SUPERTYPE of A) if anywhere an instance of B is expected an instance of A may be used instead. E.g. integer is a subtype (also subset) of real in usual mathematical usage Sometimes IS ASSIGNABLE TO is used to mean "is a subtype of". --- STRONG TYPING: cannot crash or produce nonsensical results due to objects being of the wrong type E.g. in Scheme, Smalltalk, Java, and Ada, but not C or C++ Requires automatic storage management (garbage collection) in an OO language +++ STATIC TYPING: uses compile-time analysis to catch type errors In OOP, it is a type error if an object is passed a message it does not understand. Here 'type error' excludes projections from the wrong variant of a declared union type or narrowing to the wrong subclass. E.g. in Java, Ada, C, and C++ DYNAMIC (or LATENT) typing: opposite of static typing Some or all type checks are done at run time, e.g. in Scheme or Smalltalk --- ELEMENTS OF OOP -- Data abstraction -- Objects (actors) -- Code reuse by inheritance or deligation -- Polymorphism, especially subtyping Each of these is an independent concept. They may appear in isolation or in any combination. The full power of OOP comes from using them in combination. Without objects, you're not really doing OOP. --- DATA ABSTRACTION (ADT) a.k.a. ENCAPSULATION or INFORMATION HIDING grouping of procedures that work on data of common type(s) e.g. a module or class modeled with abstract (existential) types An ABSTRACT TYPE is just a name, which hides the CONCRETE TYPE, which is the actual type available only within the data abstraction's declaration. --- MODULE: an ADT with only one instance (set of variables) In Java, a class with variables that are all - static: belonging to the class, rather than to instances, and - private: visible only within the class --- In Java an ADT may also be a class all of whose methods (including those that are inherited) are final (can't be overridden: discussed later) and without interfaces. instance variables must be private class name is the abstract type concrete type is essentially a vector of instance variables +++ C++ ADT: classes with static (C++, not Java, terminology) methods, which are the default! --- ACTORS (OBJECTS) combine data and procedure(s) (state and behavior) in a single run-time object +++ A lambda expression is effectively a class with one method (procedure call) whose instance variables are its free variables. +++ OOP: dynamic method binding in general, requires that the object contain a method table not necessary in a statically-typed language in the absense of method overriding and interfaces C++: virtual, not static, methods; not the default Java: always does not apply to static methods, if a method is final, overriding is not possible +++ method invocation by message passing: e.g. C++, Java, Smalltalk, Scheme OOP simulation generic procedures: e.g. CLOS multimethods: method selection besed on more than the first argument of a generic procedure --- Scheme OOP using message passing: objects are closures whose first argument is a symbol that selects behavior > (define s1 (make-stack)) > (define s2 (make-stack)) > ((s1 'push!) 13) > ((s2 'push!) 14) > ((s2 'push!) 15) > ((s1 'local-pushed)) 1 > ((s2 'local-pushed)) 2 > ((s1 'pushed)) 3 > ((s2 'pushed)) 3 (define make-stack (let ((pushed 0)) (lambda () (let ((stk '()) (local-pushed 0)) (lambda (message) (case message ((empty?) (lambda () (null? stk))) ((push!) (lambda (x) (set! pushed (+ pushed 1)) (set! local-pushed (+ local-pushed 1)) (set! stk (cons x stk)))) ((pop!) (lambda () (if (null? stk) (error "Stack: Underflow") (begin (set! pushed (- pushed 1)) (set! local-pushed (- local-pushed 1)) (set! stk (cdr stk)))))) ((top) (lambda () (if (null? stk) (error "Stack: Underflow") (car stk)))) ((local-pushed) (lambda () local-pushed)) ((pushed) (lambda () pushed)) (else (error "Stack: Invalid message" message)))))))) Class variables: e.g. pushed Instance variables: stk, local-pushed. --- CODE REUSE: supported by DELIGATION and INHERITANCE --- DELIGATION: a class passes on a message if it does not deal with it very dynamic: may be hard to predict behavior +++ Scheme OOP using deligation (define make-bounded-stack (lambda () (let ((bound 10) (stack (make-stack))) (lambda (message) (case message ((push!) (if (< ((stack 'local-pushed)) bound) (stack 'push!) (error "Bounded stack: bound exceeded"))) ((set-bound!) (lambda (x) (set! bound x))) (else (stack message))))))) Here the push! method of the bounded stack class OVERRIDES (takes precidence over) the push! method in the stack class, but DELIGATES control to the stack component of the bounded stack class if the push! will not exceed the stack bound. --- INHERITANCE: which method will be invoked by a given message is determined at class creation time. --- END ---