Recent from talks
Contribute something
Nothing was collected or created yet.
Object model
View on WikipediaThis article includes a list of references, related reading, or external links, but its sources remain unclear because it lacks inline citations. (March 2010) |
In computing, object model has two related but distinct meanings:
- The properties of objects in general in a specific computer programming language, technology, notation or methodology that uses them. Examples are the object models of Java, the Component Object Model (COM), or Object-Modeling Technique (OMT). Such object models are usually defined using concepts such as class, generic function, message, inheritance, polymorphism, and encapsulation. There is an extensive literature on formalized object models as a subset of the formal semantics of programming languages.
- A collection of objects or classes through which a program can examine and manipulate some specific parts of its world. In other words, the object-oriented interface to some service or system. Such an interface is said to be the object model of the represented service or system. For example, the Document Object Model (DOM) is a collection of objects that represent a page in a web browser, used by script programs to examine and dynamically change the page. There is a Microsoft Excel object model [1] for controlling Microsoft Excel from another program, and the ASCOM Telescope Driver is an object model for controlling an astronomical telescope.
Features
[edit]An object model consists of the following important features:
Object reference
[edit]- Objects can be accessed via object references. To invoke a method in an object, the object reference and method name are given, together with any arguments.
Interfaces
[edit]- An interface provides a definition of the signature of a set of methods without specifying their implementation. An object will provide a particular interface if its class contains code that implement the method of that interface. An interface also defines types that can be used to declare the type of variables or parameters and return values of methods.
Actions
[edit]- An action in object-oriented programming (OOP) is initiated by an object invoking a method in another object. An invocation can include additional information needed to carry out the method. The receiver executes the appropriate method and then returns control to the invoking object, sometimes supplying a result.
Exceptions
[edit]- Programs can encounter various errors and unexpected conditions of varying seriousness. During the execution of the method many different problems may be discovered. Exceptions provide a clean way to deal with error conditions without complicating the code. A block of code may be defined to throw an exception whenever particular unexpected conditions or errors arise. This means that control passes to another block of code that catches the exception.
See also
[edit]Literature
[edit]- Weisfeld, Matt (2003). The Object-Oriented Thought Process (2nd ed.). Sams. ISBN 0-672-32611-6.
- Fowler, Martin (1996). Analysis Patterns: Reusable Object Models. Addison-Wesley. ISBN 0-201-89542-0.
- Fisher, K.; Honsell, F.; Mitchell, J.C. (1994). "A lambda calculus of objects and method specialization". [1993] Proceedings Eighth Annual IEEE Symposium on Logic in Computer Science (PDF). pp. 3–37. doi:10.1109/LICS.1993.287603. ISBN 0-8186-3140-6. S2CID 19578302. Archived from the original (PDF) on 2018-07-03.
- Marini, Joe (2002). Document Object Model: Processing Structured Documents. Osborne/McGray-Hill. ISBN 0-07-222436-3.
- Lippman, Stanley (1996). Inside the C++ Object Model. Addison-Wesley. ISBN 0-201-83454-5.
External links
[edit]- Document Object Model (DOM) The official W3C definition of the DOM.
- "The Java Object Model"
- The Ruby Object Model: Data Structure in Detail
- Object Membership: The core structure of object-oriented programming
- Object Model Features Matrix A "representative sample of the design space of object models" (sense 1).
- ASCOM Standards web site
Object model
View on GrokipediaOverview
Definition
In computing, an object model primarily refers to a conceptual framework that describes the properties, structure, and behavior of objects within a specific programming language, technology, or system, incorporating elements such as classes, inheritance, and polymorphism to represent real-world entities and their relationships.[4] This framework serves as the foundational abstraction for object-oriented programming (OOP), enabling developers to model complex systems by defining how objects encapsulate data and operations while supporting mechanisms for code reuse and extensibility. A secondary meaning of object model pertains to a concrete collection of interconnected objects or classes that facilitates programmatic interaction with and manipulation of specific system aspects or services, such as data structures, documents, or distributed components.[5] Unlike the general OOP framework, these models are often domain-specific, providing standardized APIs for accessing and modifying resources in a structured manner. Object models promote key design principles including encapsulation, which bundles data and methods within objects to protect internal state; abstraction, which hides implementation details to focus on essential features; and modularity, which allows components to be developed, tested, and maintained independently for enhanced reusability.[4] These concepts collectively support scalable software architectures by enabling objects—typically instances of classes—to interact cohesively without exposing underlying complexities. The scope of object models ranges from broad OOP paradigms applicable across languages like Java or C++ to specialized implementations, such as the Document Object Model (DOM) for web documents, which treats HTML or XML as a navigable tree of objects for scripting and dynamic updates.Historical Context
The origins of object models trace back to the 1960s with the development of Simula, the first programming language to incorporate classes and objects specifically for simulation purposes. Norwegian computer scientists Kristen Nygaard and Ole-Johan Dahl created Simula I in the mid-1960s at the Norwegian Defense Research Establishment to support discrete event simulations using coroutines and processes. This evolved into Simula 67 in 1967, which introduced classes as templates for objects, enabling encapsulation of data and behavior for modeling complex systems like nuclear reactor operations.[6] In the 1970s and 1980s, the concepts advanced significantly through Smalltalk, developed by Alan Kay and his team at Xerox PARC, which emphasized message passing as the primary mechanism for object interaction and inheritance for reusing and extending behaviors. Smalltalk-72, released in 1972, implemented a pure object-oriented system where all computation occurred via messages sent between objects, inspired by Simula but extending it to support dynamic, reflective programming on personal computers like the Alto. By Smalltalk-76 in 1976, inheritance was refined to allow hierarchical class structures, making it easier for users to build upon existing frameworks, though multiple inheritance experiments like those in ThingLab (1977) highlighted ongoing challenges in managing complexity.[7] The 1990s marked a period of standardization and broader adoption of object models in industry frameworks. Microsoft's Component Object Model (COM), introduced in 1993 as the foundation for Object Linking and Embedding (OLE) 2.0, provided a binary standard for creating reusable, language-agnostic software components through interfaces and reference counting. In 1997, the Object Management Group (OMG) adopted the Unified Modeling Language (UML) version 1.1 as a standardized notation for visualizing, specifying, and documenting object-oriented designs, unifying earlier methods from pioneers like Grady Booch. Booch's seminal book, Object-Oriented Analysis and Design with Applications (second edition, 1994), further influenced the field by outlining practical techniques for applying classes, inheritance, and abstraction in large-scale systems.[8][9][10] From the 2000s onward, object models integrated deeply into web technologies and modern programming languages, enabling scalable applications across distributed environments. The World Wide Web Consortium (W3C) standardized the Document Object Model (DOM) Level 1 in October 1998 as a platform-neutral interface for dynamically accessing and manipulating HTML and XML document structures, laying the groundwork for client-side scripting that evolved with standards like HTML5. Languages such as Java, publicly released by Sun Microsystems on May 23, 1995, adopted object models as a core paradigm, supporting classes, inheritance, and polymorphism for platform-independent development. Similarly, Python, first released in 1991 by Guido van Rossum, incorporated object-oriented features like classes and instances from its initial version 0.9.0, promoting multi-paradigm flexibility while emphasizing readability and reuse.[11][12][13]Core Components
Objects and Classes
In object-oriented programming, a class functions as a blueprint or template that outlines the structure and behavior for creating objects, specifying attributes for data and methods for operations.[14] Classes encapsulate the common properties and functionalities shared by a group of similar entities, enabling the modeling of real-world concepts in software.[15] An object, in contrast, is a concrete instance of a class that holds specific data values in its attributes and can invoke the class's methods to perform actions.[16] Objects represent runtime entities with their own state, distinguishing them from the abstract definition provided by the class.[17] The relationship between classes and objects is established through instantiation, the process by which a class creates one or more objects, each capable of maintaining independent states while adhering to the class's structure.[15] For instance, multiple objects can be instantiated from a single class, allowing for variations such as different values in shared attributes without altering the underlying template.[18] Central to this framework are the principles of encapsulation and abstraction. Encapsulation bundles attributes and methods within a class, restricting direct external access to internal data to maintain integrity and modularity.[19] This is often enforced through access controls like private and public modifiers, promoting secure and reusable code structures.[20] Abstraction complements encapsulation by concealing implementation complexities, presenting only essential interfaces to simplify interactions and enhance maintainability.[21] A practical illustration is the Car class, which might define attributes such as color and speed, along with methods to set or retrieve these values. From this class, distinct objects can be instantiated, such as a blue sedan with a speed of 180 km/h or a red sports car capped at 300 km/h, each encapsulating its unique configuration while abstracting engine details from the user.[22]Attributes and Methods
In object-oriented programming, attributes, also known as fields or properties, represent the data components that encapsulate an object's state. These can include primitive data types such as integers or strings, or references to other objects, allowing for the representation of both simple values and complex relationships within the system.[23][24] Attributes are typically defined within a class and instantiated per object, ensuring each instance maintains its unique state independent of others.[25] Methods, often referred to as functions or operations bound to a class, define the behaviors or actions that an object can perform. They include accessor methods, such as getters, which retrieve attribute values without modifying them, and mutator methods, such as setters, which update attributes while often incorporating validation logic to maintain data integrity.[23][25] Methods operate on the object's attributes, enabling dynamic responses to external stimuli while hiding implementation details from other parts of the program.[26] Visibility modifiers, such as public, private, and protected, regulate access to attributes and methods, promoting encapsulation by restricting direct manipulation of internal state. Private attributes and methods are accessible only within the same class, preventing unintended modifications, while public ones are exposed for broader interaction.[23][24] This controlled access ensures that changes to an object's state occur only through designated methods, reducing errors and enhancing modularity.[25] The linkage between state and behavior is fundamental, as methods rely on attributes to produce outcomes, and alterations to attributes via mutators can influence subsequent method executions. For instance, validation within mutator methods—such as checking for non-negative values—preserves invariants and ensures consistent behavior across the object's lifecycle.[23][26] This interplay supports data integrity, where method results reflect the current state accurately without exposing raw attributes.[25] A representative example is aBankAccount class, where the balance attribute is a private double to store the account's monetary state, and methods like deposit(double amount) and withdraw(double amount) serve as mutators that update the balance only after validating the input (e.g., ensuring withdrawal does not exceed the balance). Getters like getBalance() provide read-only access, illustrating how methods safeguard and interact with the encapsulated state.[23][24]
Key Features
Object References
In object-oriented programming, object references are variables or handles that store the memory address of an object, enabling indirect access to the object without embedding its full data structure directly in the variable.[27] This mechanism treats the reference as an alias or pointer to the object's location in memory, facilitating efficient manipulation and interaction with the object across different parts of a program.[28] Unlike value types, which copy the entire object, references promote shared access to the same instance, which is fundamental to memory management in languages supporting object models.[29] Object references are commonly used for passing objects as parameters to methods, returning them from functions, or assigning them to variables to enable ongoing access.[30] For instance, when a method receives a reference, it operates on the original object rather than a duplicate, allowing modifications to persist beyond the method's scope.[31] This usage is prevalent in scenarios involving large or complex objects, where direct copying would be inefficient, and it underpins dynamic behaviors in object models by linking variables to object instances indirectly.[32] The primary benefits of object references include avoiding data duplication, which conserves memory and reduces overhead during operations like assignment or parameter passing.[27] They also support polymorphism by permitting a reference of a base class type to point to instances of derived classes, allowing uniform treatment of related objects through a common interface without altering the reference type.[33] In managed environments, such as Java, unreferenced objects—those with no active references pointing to them—become eligible for automatic garbage collection, where the runtime reclaims the memory they occupy to prevent leaks and optimize resource use.[34] For example, in C++, a pointer to an object can be declared using the asterisk (*) operator, such asMyClass* objPtr = new MyClass();, and used to invoke methods via the arrow operator, like objPtr->method();.[35] Similarly, a reference (&) provides an alias for direct access, as in MyClass& objRef = *objPtr; objRef.method();, both avoiding copies while ensuring the same underlying object is manipulated.[27]
Interfaces
In object-oriented programming, an interface is defined as a reference type that specifies a set of method declarations, or signatures, without providing their implementations, serving as a contract that classes can adhere to by implementing these methods.[36] These signatures include the method names, parameter types, return types, and exceptions, allowing interfaces to act as types for variables, method parameters, or return values, thereby enabling type checking at compile time.[37] The primary purpose of interfaces is to facilitate polymorphism, where objects of different classes can be treated uniformly through a shared interface, allowing a single piece of code to operate on multiple types without regard to their specific implementations.[38] This promotes loose coupling by ensuring that client code depends only on the interface rather than on concrete classes, enhancing modularity, reusability, and maintainability in software design.[36] For instance, in scenarios like robotic systems controlling vehicles from various manufacturers, an interface defining methods such asturn or changeLanes allows polymorphic substitution of different car models without altering the controlling logic.[36]
Classes implement an interface by declaring that they do so—using the implements keyword in languages like Java—and providing concrete method bodies for all declared methods, which must match the signatures exactly.[37] A single class can implement multiple interfaces, inheriting the method signatures from each and providing implementations that satisfy all contracts simultaneously.[37] This capability emulates multiple inheritance of type but avoids the complexities of implementation inheritance, as interfaces contain no instance variables or default behaviors beyond optional default methods in modern languages.[36]
A representative example is the Drawable interface, which declares a single method draw() with no parameters and a void return type.[36] Classes such as Circle and Rectangle can implement Drawable by providing their own draw() methods: Circle might render a circular shape using graphical primitives, while Rectangle draws rectangular boundaries, allowing a collection of shapes to be iterated and drawn polymorphically via the interface type.[38]
When a class implements multiple interfaces that declare methods with the same signature, any potential conflicts are resolved by the class providing a single overriding implementation that satisfies all interfaces, ensuring compatibility without ambiguity.[37] If default implementations in the interfaces differ, the class must explicitly override the method to choose or reconcile the behavior, preventing compile-time errors from override-equivalent signatures.[37] This approach supports flexible composition of behaviors across unrelated class hierarchies.[37]
Actions and Method Invocation
In object-oriented programming, actions and method invocation constitute the dynamic mechanism by which one object requests an operation from another, primarily through the paradigm of message passing. This process encapsulates interactions, allowing objects to collaborate without exposing internal state, as pioneered in early systems like Smalltalk where every computation is viewed as objects communicating via messages consisting of a selector (method name) and optional arguments. The invocation triggers the execution of a corresponding method on the receiver object, promoting modularity and abstraction in software design.[39] The invocation process typically employs syntax such asreceiver.method(arguments), where the runtime system performs dynamic dispatch to select the appropriate method implementation based on the receiver's actual type, traversing the class hierarchy if necessary. Parameters are passed either by value—creating a copy of the argument to isolate changes—or by reference, providing direct access to the original data for efficiency and modification, as seen in languages like C++ with explicit reference parameters or Java where object references are passed by value but enable state updates. Execution is predominantly synchronous, blocking the caller until the method completes and returns control, though asynchronous invocation supports non-blocking calls in concurrent contexts, such as using futures or callbacks to handle long-running operations without halting the thread. This flexibility aids in building responsive systems, particularly in multithreaded object-oriented environments.[40][41][42]
Methods often return values—such as primitive data, other objects, or void (no return)—which can be chained for fluent expression, as in obj1.method1(arg).method2(arg2), where the output of the first invocation serves as input to the next. Dynamic dispatch underpins polymorphism during invocation, resolving the correct method at runtime even if the receiver is referenced through a superclass or interface type, ensuring substitutability without altering client code. For instance, in Smalltalk, sending the message add: 5 to a collection object like an OrderedCollection invokes its add: method, which appends 5 to the collection and returns the added element, demonstrating how message passing seamlessly handles polymorphic behavior across collection types.[39][40]
Exception Handling
Exception handling in object models provides a structured mechanism for managing runtime errors that arise during object interactions, such as method invocations on objects, by allowing errors to be represented as exception objects that can be thrown and subsequently caught for recovery or graceful termination.[43] This approach separates error-handling logic from normal program flow, promoting modular and maintainable code in object-oriented systems.[44] Central to this mechanism are exception classes, which form a hierarchy typically rooted in a base class like Throwable in Java, with subclasses such as Exception for recoverable errors and RuntimeException for unchecked programming errors. Specific subclasses, like IOException, extend this hierarchy to denote domain-specific errors, enabling precise error categorization and handling. The core syntax involves try-catch-finally blocks: the try block encloses potentially erroneous code, catch blocks handle thrown exceptions by type, and the finally block ensures execution of cleanup code regardless of exception occurrence. Unhandled exceptions propagate up the call stack, starting from the method where the error occurred, until a matching catch block is found or the program terminates if none exists. This bubbling mechanism allows errors to be resolved at higher levels in the object interaction chain, supporting fault isolation in complex object-oriented designs.[43] Best practices emphasize throwing specific exception types over general ones to facilitate targeted recovery, implementing consistent logging to record error contexts without suppressing issues, and using finally blocks or equivalent constructs for resource cleanup to prevent leaks.[45] For instance, in Java, developers should prefer checked exceptions like IOException for anticipated failures and log details via mechanisms like java.util.logging to aid debugging.[45] A representative example in Java illustrates this:try {
riskyMethod(); // May throw an exception during object interaction
} catch (IOException e) {
// Handle specific error, e.g., log and retry
[System](/page/System).err.println("IO error: " + e.getMessage());
// Log or notify as per best practices
} finally {
// Cleanup resources, e.g., close streams
if ([resource](/page/Resource) != null) {
resource.close();
}
}
try {
riskyMethod(); // May throw an exception during object interaction
} catch (IOException e) {
// Handle specific error, e.g., log and retry
[System](/page/System).err.println("IO error: " + e.getMessage());
// Log or notify as per best practices
} finally {
// Cleanup resources, e.g., close streams
if ([resource](/page/Resource) != null) {
resource.close();
}
}
Applications
In Programming Languages
In programming languages, object models provide the foundational structure for organizing code around objects that encapsulate data and behavior, but their implementations differ significantly across languages to balance aspects like type safety, performance, and ease of use. Java, C++, and Python exemplify these variations, each adopting distinct approaches to inheritance, typing, and memory management while supporting core object-oriented principles such as encapsulation and polymorphism. These differences arise from design goals: Java emphasizes portability and safety through a virtual machine, C++ prioritizes low-level control and efficiency, and Python focuses on simplicity and rapid development.[46][47] Java employs a strict class-based object model where all classes implicitly extend thejava.lang.Object class, enabling single inheritance for classes while using interfaces to simulate multiple inheritance. Interfaces define contracts through abstract methods, allowing classes to implement multiple interfaces without inheriting state, which promotes loose coupling and polymorphism. Object references are managed automatically via garbage collection, where the Java Virtual Machine (JVM) identifies and reclaims unreachable objects to prevent memory leaks, contrasting with manual approaches in other languages. This model ensures type safety through static typing, where compile-time checks verify type compatibility, reducing runtime errors.[48]
C++ supports a more flexible class-based model that permits multiple inheritance, allowing a derived class to inherit from several base classes, which can lead to complex hierarchies but enables powerful code reuse, such as in mixin-style designs. To resolve ambiguities in multiple inheritance, C++ uses virtual inheritance, adjusting the object layout to avoid duplicated base class subobjects. Object references are handled via pointers and references, which provide direct memory access but require manual memory management using new and delete operators, supplemented by destructors for resource cleanup in a technique known as RAII (Resource Acquisition Is Initialization). This approach offers fine-grained control over memory but demands careful handling to avoid issues like dangling pointers or leaks. Static typing in C++ enforces type checks at compile time, supporting both object-oriented and procedural paradigms for high-performance applications.[46]
Python implements a dynamic object model where everything—integers, strings, functions, and classes—is treated as an object, inheriting from a universal base type, which unifies the language's type system and enables seamless interoperability. Unlike class-based systems, Python relies on duck typing, an implicit form of interfaces where an object's suitability for a role is determined by its behavior (e.g., possessing required methods) rather than explicit type declarations, fostering flexibility in polymorphic code without formal contracts. Memory management is automatic through reference counting combined with a cyclic garbage collector, automatically deallocating objects when their reference count reaches zero or cycles are detected. Dynamic typing defers type checks to runtime, allowing for more concise code but potentially introducing errors that static analysis might catch earlier.[47]
Comparisons across these languages reveal trade-offs in performance and flexibility: C++'s compiled nature and manual control yield superior runtime speed for compute-intensive tasks compared to Java and Python, though the exact differences depend on the task, optimizations, and libraries used (e.g., up to 10-50x faster for unoptimized numerical computations as of 2024).[49] Java strikes a balance with JVM-based just-in-time compilation, offering better portability than C++ but slower startup and higher memory overhead compared to native code. Python's interpreted execution and dynamic features prioritize developer productivity, enabling faster prototyping but generally slower execution for CPU-bound operations than C++. Static typing in Java and C++ enhances early error detection and optimization opportunities, while Python's dynamic typing supports greater code adaptability, such as runtime metaprogramming, albeit with reduced compile-time guarantees. These choices influence adoption: C++ for systems programming, Java for enterprise applications, and Python for data science and scripting.
The evolution of Java's object model illustrates adaptations to modern needs; for instance, Java 8 introduced default methods in interfaces, allowing implementations within interfaces themselves, which expands their utility beyond pure contracts to include backward-compatible enhancements without breaking existing implementers. This feature resolves limitations in the original single-inheritance model by enabling functional-style extensions, such as lambda-compatible utilities, while maintaining binary compatibility. Subsequent updates, like private methods in interfaces (Java 9), further refined this by supporting internal helper logic, enhancing modularity in large-scale object-oriented designs.[50]
