There are many definitions of an object, such as found in [Booch 91, p77]: "An object has state, behavior, and identity; the structure and behavior of similar objects are defined in their common class; the terms instance and object are interchangeable". This is a "classical languages" definition, as defined in [Coplien 92, p280], where "classes play a central role in the object model", since they do not in prototyping/delegation languages. "The term object was first formally applied in the Simula language, and objects typically existed in Simula programs to simulate some aspect of reality" [Booch 91, p77]. Other definitions referenced by Booch include Smith and Tockey: "an object represents an individual, identifiable item, unit, or entity, either real or abstract, with a well-defined role in the problem domain." and [Cox 91]: "anything with a crisply defined boundary" (in context, this is "outside the computer domain". A more conventional definition appears on pg 54). Booch goes on to describe these definitions in depth. [Martin 92, p 241] defines: "An "object" is anything to which a concept applies", and "A concept is an idea or notion we share that applies to certain objects in our awareness". [Rumbaugh 91] defines: "We define an object as a concept, abstraction or thing with crisp boundaries and meaning for the problem at hand." [Shlaer 88, p 14] defines: "An object is an abstraction of a set of real-world things such that: * all of the real-world things in the set - the instances - have the same characteristics * all instances are subject to and conform to the same rules" and on identifying objects: "What are the *things* in this problem? Most of the things are likely to fall into the following five categories: Tangible things, Roles, Incidents, Interactions, and Specifications." [Booch 91, 4.3] covers "Identifying Key Abstractions" for objects and classes based on an understanding of the problem domain and [Jacobson 92] provides a novel approach to identifying objects through use-cases (scenarios), leading to a use-case driven design. Jacobson also calls for managing complexity with specialized object categories [Jacobson 94]: Ordinary Objects - Typical OOPL objects Use-Cases and Actors - Actors <--> Use-Cases <--> Object Model Objects Megaobjects - Composite objects (~ subsystems with inheritance) Frameworks*(Typical) - Abstract MO meant for reuse and extension Patterns** (Typical) - Framework-like, crsp. classes and comm patterns only Application Objects - In the Object Model Interface - E.g. GUI Control - Introduced in design for control purposes Entity - Correspond to real-world objects Component Objects - Utility and Implementation hiding objects Utility - Set, Array, ... Impl. Hiding - Distr. Arch., specific DBMS, OS Unrelated to Ivar Jacobson but relevant to the topic: * There was a Software Frameworks Assoc. and magazine until last year, but a review of their last conference is available by email thanks to Adam Wildavsky, send requests to firstname.lastname@example.org. **There is a patterns mailing list, email: email@example.com. See also st.cs.uiuc.edu for some info on patterns.
The implementation of objects could roughly be categorized into descriptor- based, capability-based, and simple static-based approaches. Descriptor- based approaches (e.g. Smalltalk handles) allow powerful dynamic typing, as do the capability-based approaches which are typically found in object- oriented databases and operating systems (object id's). A "proxy" based approach with an added layer of indirection to Smalltalk's handles is found in Distributed Smalltalk which allows transparent, distributed, and migrating objects [Kim 89, ch 19 and Yaoqing 93]. Simple static approaches are found in languages such as C++, although the new RTTI facility will supply simple dynamic typing (checked downcasting) similar to those introduced by Eiffel in 1989 through the notion of assignment attempt, also known as type narrowing.
Descriptor-based approaches can have pointer semantics and can be statically typeless (or just "typeless", as in Smalltalk) where references (variables) have no type, but the objects (values) they point to always do. An untyped pointer (such as void* in C++) and an embedded dynamic typing scheme are used in more conventional languages to fully emulate this style of dynamically typed programming (see sections 2.3, 4.3, and [Coplien 92]).
Below is a simple example to show a most trivial case of OO implementation. It is primarily intended to introduce new terms. See [Cardelli 85] for another semantic definition of OO using functions for methods and for a view of types as sets of values.
Simple statically-typed objects (static and auto vars and temps in C++ and expanded types in Eiffel) can be viewed as instances of a record type, whose record fields are called instance variables (Smalltalk) or member data (C++). The record (class) may also contain operations which are called methods (Smalltalk) or member functions (C++) which are equivalent to a function taking an object of the record type, called the receiver, as the first parameter. The receiver is called self (Smalltalk) or this (C++). Members will denote both instance variables and methods. Inheritance is roughly equivalent to a loosely coupled variant record, with derived classes as variant parts and with multiple-inheritance concatenating several records to serve as a base.
A virtual member in statically typed languages is a base class member that can be set or respecified by a derived class. This is roughly equivalent to a pointer or function pointer in the base class being set by the derived class. [Stroustrup 90] covers the implementation details of virtual member functions in C++, which also involve an offset for the receiver to handle multiple- inheritance. This is an example of dynamic binding, which replaces a switch statement on variant parts with a single call, reducing code size and program complexity (fewer nested programming constructs) and allowing variants to be added without modifying client code (which causes higher defect injection rates during maintanance and debugging).
Virtual members in dynamically typed languages are more flexible because static typechecking requirements are dropped. See section 2.5.
The terms method/member function, instance variable/member data, subclass/ derived class, parent class/base class, and etc. will be used interchangeably. As pointed out in [Stroustrup 90, p197], the base/derived class terminology may be preferable to the sub/super-class terminology, and is preferred in this document also.
Delegation/prototyping languages [Kim 89, ch3; Ungar 87, Sciore 89] have a more flexible kind of object which can play the role of classes in classical OO languages. Since there is no separate class construct in these languages, and only objects, they are referred to as single-hierarchy, or 1 Level systems. Objects contain fields, methods and delegates (pseudo parents), whereas classical object-oriented languages associate method, field and parent definitions with classes (and only associate state and class with objects, although vtables of function pointers for dynamic binding is an exception). However, one-level objects often play the role of classes to take advantage of sharing and often instances will simply delegate to parents to access methods or shared state, otherwise idiosyncratic objects, a powerful and natural concept, will result. Typical 1 Level objects can contain any number of fields, methods and parents and any object can be used as a template/exemplar, thus performing the classical role of a class. In typical prototyping systems, parents (as any other member) can be added or changed dynamically, providing dynamic multiple inheritance (or more typically simple delegation). Here, the term "Prototype" usually refers to prototype theory, a recent theory of classification where any object can be inherited from or cloned to serve as a prototype for newly created instances. [The Author also uses the term for languages providing high quality support for rapid prototyping, although this usage is atypical] See [Booch 94, pp 154-155] for a brief discussion of prototype theory in the context of OOA and OOD.
It is common in such systems for an object to "become" another kind of object by changing its parent. A good example is a window becoming an icon, as window and icon objects display different behavior (although cognitive differences are significant too:-) Delegation refers to delegating the search for an attribute to a delegate, and is therefore more of a pure message passing mechanism (as with dynamic scoping) than inheritance, which also typically specifies non-shared state when used for representation.
Chambers has proposed an interesting variation called "Predicate Classes" [Chambers 93] as a part of his Cecil language. These classes will only be parents when certain predicates are true. This can support a types/classes as collections of objects view, which is the same as the types as sets of values view taken by [Cardelli 85]. [Martin 92] provides some examples of this view applied during OOA.
1 level systems therefore provide the most flexible and powerful capabilities. Self is a good example of a delegation-based single hierarchy language [Ungar 87].
This document was translated by ms2html v1.8 on 01.06.95.