X3J3/96 - 114 Date: May 17, 1996 To: X3J3 From: /OOF Subject: OOF Terminology Tutorial OOF Tutorial John S. Cuthbertson 17th May 1996 INTRODUCTION o Intention of this tutorial + Aim to show that some form of Object Oriented Programming is possible with minimal language change + Reasons for minimal changes to the language: - less painful to implementors - less confusing to users - more chance of OOF being accepted by both implementors and users o Scope of this tutorial + Introduce and explain "unfamiliar" terminology + Explain the semantics of this terminology + Provide examples (if possible) of how these semantics may be achieved in Fortran Notes: /oof initially only expects to introduce the basic or "core" functionality of Object Orientation, but in a way that may be readily extended. Any syntactic sugar or "new" constructs are for illustration only. This tutorial in not a rationale on why Object Oriented Programming should be supported in Fortran, that should come in the tutorial at the November meeting. OBJECT ORIENTED TERMINOLOGY o Encapsulation In OOP encapsulation is just information hiding, with access to the representation being restricted. Manipulation of an object is performed by using the implemented operations or procedures. Common in Abstract Data Types, and the mechanism already exists in Fortran with derived-types with PRIVATE components. o Object An object in OOP is just a data object, usually some form of structure of instance of derived-type. May also be thought of as an instance (or value) of an abstract data-type. o Class A class is set of "things" that are related in behavior and/or form. For example the Fortran numeric types have similar behavior in that the arithmetic operations are defined for them. This could possibly be the class of Number. o Methods or Operations In OOP a method is just some sort of procedure that is associated (or tagged) to an object or class. In OOF a method is just a Fortran procedure, it will usually be defined in a module, but it will be associated with a derived-type. o Message Passing In OOP a message is passed to an object to: + enquire about the status of the object + to manipulate the object in some way. Message passing is how OOP refers to procedure calling. In all Object Oriented Programming Languages message passing is "implemented by" procedure calling. For example, the OOP statement: SEND John THE MESSAGE present(oof_tutorial) may cause the John object to reflect that a change in underwear is required. The OOP statement: SEND John THE MESSAGE change_underwear may cause this change. In OOF these messages can be passed to John using the normal subroutine or function call: PRESENT(JOHN, OOF_TUTORIAL) CHANGE_UNDERWEAR(JOHN) o Specialization Specialization is how the IS_A relationship is referred to in OOP. The IS_A relationship is common and occurs when something is more restricted or "specialized" than something else e.g. Fortran is_a Programming Language Alternatively specialization can be thought of extending the behavior and/or the representation of a class or object. o Inheritance Inheritance is typically used to implement specialization, or to extend a type or class. Typically when B "inherits" from A, the components and procedures that are defined for A are obtained, for free, by B. With inheritance, A is said to be the "parent" and B is referred to as the "child". In OOF inheritance will be referred to as "B extends A". Semantically similar to defining a sub-component, of type A, in B. For example given the following derived-type: TYPE POINT REAL :: X,Y END TYPE POINT then "COLORED_POINT extends POINT" is similar to: TYPE COLORED_POINT TYPE(POINT) :: parent INTEGER :: COLOR END TYPE COLORED_POINT However inclusion of the parent component requires access to the components of COLORED_POINT using up-to 2 levels of component selection. Only one level of component selection is probably more desirable. /oof would like to see the following "sort" of derived type definition: TYPE COLORED_POINT EXTENDS(POINT) :: PARENT INTEGER :: COLOR END TYPE COLORED_POINT TYPE(COLORED_POINT) :: CP Access to the components of COLORED_POINT via CP%X, CP%Y, and CP%COLOR. Access to the PARENT sub-component as a whole should also be allowed. An inheritance chain is when we have the situation type B extends type A and type C extends type B; the content of the chain is A, B, C. o Polymorphism Polymorphism is a form of sub-type/super-type relationship. Allows use of an instance of sub-type where an instance of super-type is required. For example: INTEGER(KIND=1) is usually a sub-type of default integer. INTEGER(KIND=1) can be used in places where a default integer may be used. Polymorphism implies a constrained relaxation of the type rules, constrained that is so that it operates only on objects of derived-type and where there is some extra syntax. A procedure is said to be polymorphic when, given that B extends A and C extends B, the procedure is: + generic, and + the type of its first actual argument is one + of A, B, or C. o Overloading An operator or procedure is "overloaded" if there is more than one operation with the same name, that is distinguished by the types of the arguments. By default the / operator is overloaded to one "divide" operation that is defined for REALs and a different operation that is defined for INTEGERs. This is identical to the Fortran "generic" facility. o Late or Run-time Resolution Effectively occurs at the call of a generic procedure when given an actual argument whose type is one of an inheritance chain. Resolution, i.e. selection of the specific procedure cannot take place at compile-time as the actual procedure selected depends on the actual argument. Resolution must then take place at run-time; hence the name "late resolution". Some syntactic sugar should be introduced to actually indicate that late-resolution may take place. EXAMPLES ! Ex 1 - overloading, but not polymorphism module bp type point private real :: x, y end type point interface move module procedure move end interface contains type(point) function move(p, d, angle) type(point), intent(in) :: p real, intent(in) :: d, angle move%x = .... move%y = .... end function move end module bp module cp use bp type colored_point private extends(point) :: cpt integer :: color end type colored_point interface move module procedure cmove end interface move contains subroutine print_colored_point(p) type(colored_point) :: p print *, p%x, p%y, p%color end subroutine print type(colored_point) function cmove(p, d, angle) type(colored_point) :: p real :: d, angle print_colored_point(p) cmove%cpt = move(p%cpt, d, angle) cmove%color = p%color end function cmove end module cp o This is not polymorphic as the generic move can be resolved through the first argument. // Ex 1a C++ // file : bp.h class point { public: void move(float d, float angle); private: float x, y; }; void point::move(float d, float angle) { this->x = ....; this->y = ....; } // eof // file : cp.h class colored_point : private point { public: void move(float d, float angle, int color); private: int color; }; void colored_point::move(float d, float angle, int color) { (point *)this->move(d, angle); this->color = color; } ! Ex 2 - polymorphic example, requiring resolution of the ! move procedure to run-time. module m1 private public point, move type point real :: x, y end type point interface move module procedure move end interface contains subroutine print(self) type(point), intent(in) :: p write(*, "('(',F15.8,',',F15.8,')')") self%x, self%y end subroutine print end module module m2 use m1 private public colored_point, move type colored_point extends(point) :: parent integer :: color end type colored_point interface move module procedure cprint end interface contains subroutine cprint(self) type(colored_point) :: self write(*, "('(x=',F15.8,',y=',F15.8,',color=',I4,')')" & self%x, self%y, self%color end subroutine cprint end module program use m1 use m2 type point_ptr class(point), pointer :: pnt ! syntactic 'hook' signifying ! possible run-time resolution end type point_ptr type(point_ptr) :: collection(120) call read_em_in(collection) ! read selection of points ! and colored_points do i = 1, 120 call print(collection(i)) ! run-time resolution as cannot ! determine if collection(i) is ! type(point) or type(colored_point) end do end program // Ex2 C++ // file : m1.h class point { public: virtual void print(void); // syntactic hook signifying print // polymorphic private: float x, y; }; virtual void point::print(void) { cout << this->x << this->y; } // file : m2.h class colored_point : private point { private: int color; // No need to redeclare x, y, and move } virtual void colored_point::print(void) { cout << this->x << this->y << this-color; } void main(void) { point* collection[120]; int i; read_em_in(collection); for (i=0; i < 120; i++) { *collection[i].print(); // call on polymorphic procedure // requiring a run-time resolution } } // eof CONCLUSION With this tutorial we hope we have: + introduced and simplified the main OO terminology + introduced the basic OO semantics + shown that supporting Object Oriented Programming can be "relatively" painless. Remember: + nothing is concrete + /oof is open to suggestion over additional requirements and semantics, and preference over syntax + /oof would like your help. FUTURE PLANS Nov '96 - Rationale Tutorial May '97 - Semantic specs Nov '97 - X3J3 consensus on syntax May '98 - Edits with no more controversy. POSSIBLE STRAW VOTES Do people: + agree with the model or notion of inheritance, i.e. B extends A ? + agree with the mechanism of associating procedures with types ? ***************************************************************************** * John S. Cuthbertson (johnc@epc.co.uk) . * * _,'| _.-''``-...___..--';)* * Edinburgh Portable Compilers /_ \'. __..-' , ,--...--''' * * 17 Alva Street, Edinburgh <\ .`--''' ` /' * * Scotland, EH2 4PH `-';' ; ; ; * * Tel: 44 (0)131 225 6262 __...--'' ___...--_..' .;.' * * Fax: 44 (0)131 225 6644 (,__....----''' (,..--'' * *****************************************************************************