EEiiffeffell aanndd CC++++

A comparison between two Object-Oriented languages

Tom Van Cutsem CCllaasssseess aanndd OObbjjeecctsts

 Both Eiffel and C++ are statically typed, class- based object-oriented languages.  Both regard class definitions as type definitions.  Both make a clear distinction between classes and objects.  Eiffel is a pure object-oriented language, C++ is impure (multi-paradigm). CCllaasssseess aanndd OObbjjeecctsts CC++++  State encapsulated in ‘data members’.  Behaviour encapsulated in ‘memberfunctions’.  Manual memory Management  Four so called ‘special member functions’: the constructor, the destructor, the copy constructor and the assignment operator. CCllaasssseess aanndd OObbjjeecctsts EEiiffeffell Automatic Garbage Collection Eiffel classes consist of features:

class HELLO create make feature make is -- Print a simple message. do io.put_string ("Hello World") io.put_new_line end end -- class HELLO CCllaasssseess aanndd OObbjjeecctsts EEiiffeffell  Two viewpoints on features.  From the viewpoint of the defining class, a feature is an attribute, a function or a procedure.  From the viewpoint of the client class, a feature is a command or a query. Client Supplier Procedure Command Function Feature Query Attribute CCllaasssseess aanndd OObbjjeecctsts EEiiffeffell  The client class does not see the difference between attribute access and a parameterless function call: the Uniform Access Principle

myBalance := myAccount.balance

implemented as an attribute

class ACCOUNT feature balance: INTEGER end CCllaasssseess aanndd OObbjjeecctsts EEiiffeffell  The client class does not see the difference between attribute access and a parameterless function call: the Uniform Access Principle

myBalance := myAccount.balance implemented as a function class ACCOUNT feature -- an instance variable thebalance: INTEGER feature -- access the balance balance is do balance := thebalance end CCllaasssseess aanndd OObbjjeecctsts

 In C++, classes without ancestors become the root of a new hierarchy.  Eiffel has a root class, ANY, which exports features like cloning, comparison, …  Eiffel also defines a ‘least class’, NONE, with its sole instance Void. ANY

… … … NONE InInfoforrmmaatitioonn HHiiddiinngg

 C++ defines a plethora of keywords to restrict access to members (public,private, protected, friend, …)  Eiffel uses ‘export clauses’ to denote which classes (and subclasses) get to see certain features.  Attributes can never be assigned to from outside the class, even when ‘public’. class ACCOUNT feature { NONE } -- “Private” balance: INTEGER feature -- “Public” deposit (sum: INTEGER) is do … end feature { ACCOUNT } -- “Protected” connect (bankcomputer: COMPUTER) is do … end feature { COMPUTER } -- COMPUTER is a ”friend” validate (password: STRING) is do … end end InInhheerriitatannccee MMooddeell CC++++  Both Eiffel and C++ allow multiple inheritance.  C++ allows ‘private inheritance’ to support ‘subclassing for construction’.  Sharing in repeated inheritance is accomplished by ‘virtual inheritance’.  Name clashes are solved through explicit qualification of the scope using the scope- resolution (‘::’) operator. InInhheerriitatannccee MMooddeell EEiiffeffell class ASSISTANT inherit STUDENT TEACHER feature …  feature adaption clauses are provided to change inherited features.  The redefinition clause specifies which methods are overridden. class SAVINGS_ACCOUNT inherit ACCOUNT redefine deposit end feature -- new implementation deposit (sum : INTEGER) is do … end InInhheerriitatannccee MMooddeell EEiiffeffell  The renaming clause specifies new names for inherited methods. This is also used to avoid name clashes. class ARRAYED_LIST inherit LIST ARRAY rename count as capacity, item as array_item end feature …

 The undefine clause uneffects features which is usefull when a class inherits two implementations for conceptually the same method. InInhheerriitatannccee MMooddeell EEiiffeffell  Repeated inheritance is solved on a per-feature basis, rather than on a per-class basis.  By renaming a repeated feature, a duplicate is made. If nothing is renamed, then the repeated features are folded into one. InInhheerriitatannccee MMooddeell EEiiffeffell class ASSISTANT inherit TEACHER rename computer_account as faculty_account select faculty_account end STUDENT rename computer_account as student_account end end  The Select Clause is used to solve ambiguous calls, for example: p : PERSON create { ASSISTANT } p.make(“John Doe”) … p.computer_account … MMiixxiinnss class Person { string name; public: virtual void display() const { cout << name; } }; template class Doctor_mixin: public virtual T { public: virtual void display() const { cout << "Dr. "; T::display(); } }; template class Professor_mixin: public virtual T { public: virtual void display() const { cout << "Prof. "; T::display(); } }; class ProfessorDoctor: public virtual Professor_mixin > {}; class DoctorProfessor: public virtual Doctor_mixin > {}; MMiixxiinnss

Axiom (shared) f() = 0

Implementation Interface f() { … } g() { f(); }

Mixin MMiixxiinn EExxaammppllee Axiom class Sequence { virtual void push_front(T elt) = 0; … };

Implementation Interface class Array: public virtual Sequence { … }; class Stack: public virtual Sequence { class List: public virtual Sequence { … }; virtual void push(T elt) { push_front(elt); } }; class Queue: public virtual Sequence { virtual void enqueue(T elt) { push_front(elt); } };

Mixin class ArrayStack: public virtual Array, public virtual Stack { }; class ListQueue: public virtual List, public virtual Queue { }; TTyyppee MMooddeell

 Both Eiffel and C++ allow polymorphic assignments based on subclassing (subclassing is interpreted as subtyping).  Safe downcasting in C++ through a dynamic_cast:

Derived* derived = dynamic_cast(base); if (derived != 0) …  In Eiffel, use an ‘assignment attempt’:

subclassObj ?= superclassObj if (subclassObj /= Void) then … GGeenneerriiccss

 C++ introduces Template functions or classes.  Unconstrained: the constraints on the parameters are implicit in the body of the function or class.  Eiffel introduces Generic classes with ‘formal generic parameters’.  Introduces constrained genericity, for example: class SORTABLE_ARRAY [G  COMPARABLE] feature … end DDeessiiggnn BByy CCoonntrtraacctt EEiiffeffell  Client classes must conform to a ‘contract’ before being able to use services provided by a supplier.  Supplier classes must conform to that ‘contract’ by ensuring they provide the correct services.  Supported in Eiffel through pre- and postconditions and class invariants.  Preconditions are inherited by ‘OR-ing’ them together, postconditions by ‘AND-ing’. DDeessiiggnn BByy CCoonntrtraacctt EEiiffeffell class ACCOUNT feature balance: INTEGER deposit_count: INTEGER -- number of deposits made since opening all_deposits: DEPOSIT_LIST -- list of deposits since account's opening feature deposit (sum: INTEGER) is precondition require non_negative: sum >= 0 do … postcondition ensure one_more_deposit: deposit_count = old deposit_count + 1 updated: balance = old balance + sum Class end invariant invariant consistent_balance: (all_deposits /= Void) implies (balance = all_deposits.total) zero_if_no_deposits: (all_deposits = Void) implies (balance = 0) end -- class ACCOUNT VVaarriiaannccee RRuulleess CC++++  C++ is agnostic (or non-variant) with respect to method arguments.  Allows covariant semantics on return types, which is type safe: class Parent { public: virtual Parent* clone() { … return abase; } }; class Child: public Parent { public: virtual Child* clone() { … return aderived; } }; Parent* aparent = new Child; Parent* result = aparent->clone(); VVaarriiaannccee RRuulleess EEiiffeffell  Eiffel uses covariant semantics for both return types and arguments.  Allowing covariant semantics on arguments can compromise static typing:

class PLOT class PLOT_3D feature inherit PLOT redefine add end add(covar:DATASAMPLE) is … feature add(covar:DATASAMPLE_3D) is …

plot : PLOT plot3D : PLOT_3D sample : DATASAMPLE plot := plot3D plot.add(sample) VVaarriiaannccee RRuulleess EEiiffeffell  Eiffel uses implicit covariance in its generic types: polymorphic assignments between A[X] and A[Y] are possible if X and Y are related through inheritance. This is similar to Java arrays, and also causes type-safety problems:

girlsOnly : VECTOR [PERSON] aBoy : PERSON create {VECTOR[GIRL]} girlsOnly -- allowed with covariance create {BOY} aBoy -- permitted by principle of substitution girlsOnly.append(aBoy) -- girlsOnly now holds a Boy AAnncchhoorreedd TTyyppeess

 Eiffel introduces ‘anchored types’ to support working with covariance.  Variables declared as: ‘x: like obj’ will be assigned the static type of obj.  Anchored types are usually used with Current in a method declaration: when the method is inherited, its type signature changes

acluastso AmCCOaUtNiTcally. class BUSINESS_ACCOUNT feature inherit ACCOUNT owner : PERSON feature set_owner(new: like owner ) is owner : BUSINESS_PERSON … … end end … end MMeeththoodd LLooookkuupp

 Eiffel always uses dynamic binding (static binding when appropriate).  C++ employs a default policy of static binding.

C++ binding policy

Method is non-virtual Method is virtual Automatic Variables Static Binding Static Binding References & Pointers Static Binding Dynamic Binding MMeeththoodd LLooookkuupp CC++++  Implementation via a ‘virtual function table’ which is shared at run-time by all objects of the same class.  uses lexical addressing through offsets in the vtable. Overridden methods are placed at the same index, but point to different code.

class A { class B: public A { virtual void f() { … } virtual void g() { … } }; virtual void f() { … } }; i i i+1 … …

code for A::f code for B::f code for B::g OOppeenn CC++++

 Open C++ is a MOP that allows the programmer to define a metaclass for each class defined in the ‘base program’.  Open C++ provides a framework for metaclasses, and provides useful introspective methods and classes (eg. a class that represents the parse-tree of the program, which can then be modified).  Classes are represented as ‘class metaobjects’ at the metalevel. Metaclasses are classes whose instances are class metaobjects.  Metaclasses inherit from the metaclass ‘Class’. OOppeenn CC++++

Metaclass declaration //base level program metaclass VerboseClass Person; class Person { int age() { return age; } };

//meta-level program Insert sequence operator to class VerboseClass: public Class { avoid interference with base level public: PTree* TranslateMemberCall(Environment* e, Ptree* obj,Ptree* op, Ptree* member, Ptree* arglist) { return PTree::Make(“(print(%p)),%p”,member, Class::TranslateMemberCall(e,obj,op,member,arglist)); } Super send to perform }; actual member call CCoonnccuurrrreennccyy

 Neither Eiffel nor C++ support concurrency as a standard language feature.  Meyer proposes his own model for concurrency in Eiffel. SSCCOOOOPP

 SCOOP (Simple concurrent object-oriented programming) was introduced by Meyer to support concurrency for Object-oriented languages in general.  Accomplish a system where synchronisation is implicit in the communication.  Communication is represented through method calls. SSCCOOOOPP

 In SCOOP, a distinction is made between objects executing on different ‘processors’.  When a variable is declared as ‘separate’, this implies the thread of the object that variable is holding is different from the current thread.

Subsystem on processor A Subsystem on processor B

p : separate PERSON p SSCCOOOOPP

 Instead of introducing new keywords, concurrent semantics are now defined by redefining the usual object-oriented semantics when dealing with ‘separate’ objects.  When invoking a command on a separate object, the caller does not need to wait (asynchronous call).  When invoking a query on a separate object, the caller must wait for the result to return (wait-by- necessity). SSCCOOOOPP  Preconditions are no longer assertion mechanisms. Applied to separate objects, they are wait conditions. class BOUNDED_BUFFER [G] feature empty, full: BOOLEAN put (x: G) is require not full … ensure not empty end remove is require not empty … ensure not full end … SSCCOOOOPP

 When calling a method, the call must wait until every object attached to a separate argument is free and every separate precondition clause is satisfied.  Synchronisation is based on object state: the set of messages an object will accept will depend on its state. CCoonncclluussiioonnss

 C++: multi-paradigm and efficient.  Eiffel: higher-level language, type system contains holes but still safer than C++.  The efficiency policy of C++ (stack-allocation and static binding, no garbage collection) conflicts with Object-oriented programming.  Neither language provides standard metaprogramming or concurrency facilities.