chapter,1 2

57
Each copy of the bank account object would be alike in the methods it offers for manipulating or reading its data, but the data inside each object would differ reflecting the different history- of each account. Objects can be thought of as wrapping their data within a set of functions designed to ensure that the data are used appropriately, and to assist in that use. The object's methods will typically include checks and safeguards that are specific to the types of data the object contains. An object can also offer simple-to-use, standardized methods for performing particular operations on its data, while concealing the specifics of how those tasks are accomplished. In this way alterations can be made to the internal structure or methods of an object without requiring that the rest of the program be modified. This approach can also be used to offer standardized methods across different types of objects. As an example, several different types of objects might offer print methods. Each type of object might implement that print method in a different way, reflecting the different kinds of data each contains, but all the different print methods might be called in the same standardized manner from elsewhere in, the program. These features become especially useful when more than one programmer is contributing code to a project or when the goal is to reuse code between projects. object-Oriented programming has roots that can be traced to the 1960s. As hardware and software became increasingly complex, manageability often became a concern. Researchers studied ways to maintain software quality and developed object-oriented programming in part to address common problems by strongly emphasizing discrete, reusable units of programming logic. The technology focuses on data rather than processes, with programs composed of self-sufficient modules ("classes"), each instance of which ("objects") contains all the information needed to manipulate its :ture ("members"). This is in contrast to the existing modular at had been dominant for many years that focused on the function of ratr.er than specifilata, h equally provided for code reuse, and reusable units of programming logic, enabling collaboration through Mules (subroutines). An object-oriented program may thus be viewed as a collection of interacting objects, the conventional model, in which a program is seen as a list of tasks (mesh) to perform. In OOP, each object is capable of receiving messages, and sending messages to other objects. Each object can be viewed nachine" with a distinct roie or responsibility. The actions (or se objects are closely associated'with the object. For

Upload: tbijle

Post on 21-Dec-2015

214 views

Category:

Documents


0 download

DESCRIPTION

dsfsdfdssssssssssssssssssssssssssssssssssss

TRANSCRIPT

Each copy of the bank account object would be alike in the methods it offers for manipulating or reading its data, but the data inside each object would differ reflecting the different history- of each account. Objects can be thought of as wrapping their data within a set of functions designed to ensure that the data are used appropriately, and to assist in that use. The object's methods will typically include checks and safeguards that are specific to the types of data the object contains. An object can also offer simple-to-use, standardized methods for performing particular operations on its data, while concealing the specifics of how those tasks are accomplished. In this way alterations can be made to the internal structure or methods of an object without requiring that the rest of the program be modified. This approach can also be used to offer standardized methods across different types of objects. As an example, several different types of objects might offer print methods. Each type of object might implement that print method in a different way, reflecting the different kinds of data each contains, but all the different print methods might be called in the same standardized manner from elsewhere in, the program. These features become especially useful when more than one programmer is contributing code to a project or when the goal is to reuse code between projects.

object-Oriented programming has roots that can be traced to the 1960s. As hardwareand software became increasingly complex, manageability often became a concern.Researchers studied ways to maintain software quality and developed object-orientedprogramming in part to address common problems by strongly emphasizing discrete,reusable units of programming logic. The technology focuses on data rather thanprocesses, with programs composed of self-sufficient modules ("classes"), eachinstance of which ("objects") contains all the information needed to manipulate its:ture ("members"). This is in contrast to the existing modularat had been dominant for many years that focused on the function ofratr.er than specifilata, h equally provided for code reuse, andreusable units of programming logic, enabling collaboration throughMules (subroutines).

An object-oriented program may thus be viewed as a collection of interacting objects,the conventional model, in which a program is seen as a list of tasks(mesh) to perform. In OOP, each object is capable of receiving messages,and sending messages to other objects. Each object can be viewednachine" with a distinct roie or responsibility. The actions (orse objects are closely associated'with the object. For example, OOPtend to "carry their own operators around with them" (or at leastan from a similar object or class) - except when they have to be

id "oriented" in something like the modern sense of object-eem to make their first appearance at MIT in the late 1950senvironment of the artificial intelligence group, as early asnrid refer to identified items. (LISP atoms) with properties (attributes);entailed understanding of LISP internals as a. strongirjcrg

Another early MIT example was Sketchpad created by Ivan Sutherland in 1960-61; in the glossary of the 1963 technical report based on his dissertation about Sketchpad, Sutherland defined notions of "object" and "instance" (with the class concept covered by "master" or "definition"), albeit specialized to graphical interaction. Also, an MITALGOL version, AED-0, linked data structures ("plexes", in that dialect) directly with procedures, prefiguring what were later termed "messages", "methods" and "member functions".Objects as a formal concept in programming were introduced in the 1960s in Simula 67, a'major revision of Simula I, a programming language designed for discrete event simulation, created by Ole-Johan Dahl and Kristen Nygaard of the Norwegian Computing Center inOslo. Simula 67 was influenced by SIMSCRIPT and C.A.R, "Tony" Hoare's proposed "record classes". , Simula introduced the notion of classes and instances or objects (as well as subclasses, virtual methods, coroutines, and discrete event simulatiop) as part of an explicit programming paradigm. The language also used automatic garbage collection that had been invented earlier for the functional programming language Lisp. Simula was used for physical modeling, such as models to study and improve the movement of ships and their content through cargo ports. The ideas of Simula 67 influenced many later languages, including Smalltalk, derivatives of LISP (CLOS), Object Pascal, and C+ + .

The Smalltalk language, which was developed at Xerox PARC {by Alan Kay and others) in the 1970s, introduced the term object-oriented programming to represent the pervasive use of objects and messages as the basis for computation. Smalltalk creators were influenced by the ideas introduced in Simula 67, but Smalltalk was . designed to be a fully dynamic system in which classes could be created and modified dynamically rather than statically as in Simula 67. Smalltalk and with it OOP were introduced to a wider audience by the August 1981 issue of Byte Magazine. In the 1970s, Kay's Smalltalk work had influenced the Lisp community to incorporate object-based techniques that were introduced to developers via the Lisp machine. Experimentation with various extensions to Lisp (like LOOPS and Flavors introducing multiple inheritance and mixins), eventually led to the Common Lisp Object System (CLOS, a part of the first standardized object-oriented programming language, ANSI Common Lisp), which integrates functional programming and object-oriented programming and allows extension via a Meta-object protocol. In the 1980s, there were a few attempts to design processor architectures that included hardware support for objects in memory but these were hot successful. Examples include the Into] iAPX 432 and the Linn Smart Rekursiv.

Object-oriented programming developed as the dominant programming methodology in the early and mid 1990s when programming languages supporting the techniques became widely available. These included Visual FoxPro 3.0, C++, and Delphi, its dominance was further enhanced by the rising popularity of graphical user interfaces, which rely heavily upon object-oriented programming techniques. An example of a closely related dynamic GUI library and OOP language can be found in the Cocoa frameworks on Mac OS X, written in Objective-C, an object-oriented, dynamic messaging extension to C based on Smalltalk. OOP toolkits also enhanced the popularity of event-driven programming (although this concept is not limited to OOP). Some feel that association with GUIs (real or perceived) was what propelled OOP into the programming mainstream.

At ETH Zurich, Niklaus Wirth and his colleagues had also been investigating such topics as data abstraction and modular programmingfalthough this had been in common use in the 1960s or earlier). Modula-2 (1978) included both, and their succeeding design, Oberon, included a distinctive approach to object orientation, classes, and such. The approach is unlike Smalltalk, and very unlike C+ + .

Object-oriented features have been added to many existing languages during that time, including Ada, BASIC, Fortran, Pascal, and others. Adding these features to languages that were not initially designed for them often led to problems with compatibility and maintainability of code.

More recently, a number of languages have emerged that are primarily object-oriented yet compatible with procedural methodology, such as Python and Ruby. Probably the most commercially important recent object-oriented languages are Visual Basic.NET (VB.NET) and C#, both designed for Microsoft's .NET platform, and Java, developed by Sun Microsystems. Both frameworks show the benefit of using OOP by creating an abstraction from implementation in their own way. VB.NET and C# support cross-language inheritance, allowing classes defined in one language to sasses defined in the other language. Developers usually compile Java tobytecode, allowing Java to run on any operating system for which a Java virtual machine is available. VB.NET and C# make use of theStrategy pattern to accomplish cross-language inheritance, whereas Java makes use of the Adapter pattern.

Just as procedural programming led to refinements of techniques such as structured programming, modern object-oriented software design methods include refinements such as the use of design patterns, design by contract, and modeling languages(suchasUML). •

Fundamental features and concepts:

A survey by Deborah J. Armstrong of nearly 40 years of computing literature identified a number of "quarks", or fundamental concepts, found in the strong majority of definitions of OOP. Not all of these concepts are to be found in all object-oriented programming languages. For example, object-oriented programming that uses classes is sometimes. called class-based programming, while prototype-based programming does not typically use classes. As a result, a significantly different yet analogous terminology is used to define the concepts of object and instance.

Benjamin C. Pierce and some other researchers view as futile any attempt to distill ' OOP to a minimal set of features. He nonetheless identifies fundamental features that support the OOP programming style in most object-oriented languages:

• Dynamic dispatch - when a method is invoked on an object, the object itself determines what code gets executed by looking up the method at run time in a table associated with the object. This feature distinguishes an object from an abstract data type (or module), which has a fixed (static) implementation of the operations for all instances. It is a programming methodology that gives modular component development while at the same time being very efficient.

• Encapsulation (or multi-methods, in which case the state is kept separate)

• Subtype polymorphism

• Object inheritance (or delegation)

• Open recursion - a special variable (syntactically it may be a keyword), usually called this or self, that allows a method body to invoke another method body of the same object. This variable is late-bound; it allows a method defined in one class to invoke another method that is defined later, in some subclass thereof.

Similarly, in his 2003 book, Concepts in programming languages, John C. Mitchell identifies four main features-, dynamic dispatch, abstraction, subtype polymorphism, and inheritance. Michael Lee Scott in Programming Language Pragmatics considers only encapsulation, inheritance and dynamic dispatch. Additional concepts used in object-oriented programming include:

• Classes of objects

• Instances of classes

• Methods which act on the attached objects.

• Message passing

• Abstraction

Decoupling:

Decoupling refers to careful controls that separate code modules from particular usecases, which increases code re-usability. A common use of decoupling in OOP is topolymorphically decouple the encapsulation (see Bridge pattern and Adapter pattern)- for example, using a method interface which an encapsulated object must satisfy, asopposed to using the object's class. ' ,

Formal semantics:

There have been several attempts at formalizing the concepts used in object-oriented programming. The following concepts and constructs have been used as interpretations of OOP concepts:

• coalgebraic data types

• abstract data types (which have existential types) allow the definition of modules but these do not support dynamic dispatch

• recursive types

• encapsulated state .

• Inheritance

• records are basis for understanding objects if function literals can be stored in fields (like in functional programming languages), but the actual calculi need be considerably more complex to incorporate essential features of OOP. Several extensions of System F<:that deal with mutable objects have been studied; these

, allow both subtype polymorphism and parametric polymorphism (generics)_______

Another scripting language that takes this approach is Lua. Earlier versions of ActionScript (a partial superset of the ECMA-262 R3, otherwise known as ECMAScript) also used a prototype-based object model. Later versions of ActionScript incorporate a combination of classification and prototype-based object models based largely on the currently incomplete ECMA-262 R4 specification, which has its roots in an early JavaScript 2 Proposal. Microsoft's JScript.NET also includes a mash-up of object models based on the same proposal, and is also a superset of the ECMA-262 R3 specification.

Design patterns:

Challenges of object-oriented design are addressed by several methodologies. Most common is known as the design patterns codified by Gamma et al.. More broadly, the term "design patterns" can be used to refer to any general, repeatable solution to a commonly occurring problem in software design. Some of these commonly occurring problems have implications and solutions particular to object-oriented development. Inheritance and behavioral subtyping

It is intuitive to assume that inheritance creates a semantic "is a" relationship, and thus to infer that objects instantiated from subclasses can always be safely used instead of those instantiated from the superclass. This intuition is unfortunately false in most OOP languages, in particular in all those that allow mutable objects. Subtype polymorphism as enforced by the type checker in OOP languages (with mutable objects) cannot guarantee behavioral subtyping in any context. Behavioral subtyping is undecidable in general, so it cannot be implemented by a program (compiler). Class or object hierarchies need to be carefully designed considering possible incorrect uses that cannot be detected syntactically. This issue is known as the Liskov substitution principle.

Gang of Four design patterns:

Design Patterns: Elements of Reusable Object-Oriented Software is an influential book published in 1995 by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, often referred to humorously as the "Gang of Four". Along with exploring the capabilities and pitfalls of object-oriented programming, it describes 23 common programming problems and patterns for solving them. As of April 2007, the book was in Us 36th printing.

The book describes the following patterns:

« Creational patterns (5): Factory method pattern, Abstract factory pattern, Singleton pattern, Builder pattern, Prototype pattern

• Structural patterns (7): Adapter pattern, Bridge pattern, Composite pattern, Decorator pattern, Facade pattern, Flyweight pattern,Proxy pattern

• Behavioral patterns (11): Chain-of-responsibility pattern, Command pattern, Interpreter pattern, Iterator pattern, Mediator pattern,Memento pattern, observer pattern, State pattern, Strategy pattern, Template method pattern, Visitor pattern...

Object-orientation and databases:

Both object-oriented programming and relational database management systems (RDBMSs) are extremely common in software today. Since relational databases don't store objects directly (though some RDBMSs have object-oriented features to approximate this), there is a general need to bridge the two worlds. The problem of bridging object-oriented programming accesses and data patterns with relational databases is known as Object-Relational impedance mismatch. There are a number of approaches to cope with this problem, but no general solution without downsides. One of the most common approaches is object-relational mapping, as found in libraries like Java Data Objects and Ruby on Rails' ActiveRecord.

There are also object databases that can be used to replace RDBMSs, but these have not been as technically and commercially successful as RDBMSs.

Real-world modeling and relationships:

OOP can be used to associate real-world objects and processes with digital counterparts. However, not everyone agrees that OOP facilitates direct real-world mapping (see Negative Criticism section) or that real-world mapping is even a worthy goal; Bertrand Meyerargues in Object-Oriented Software Construction that a program is not a model of the world but a model of some part of the world; "Reality is a cousin twice removed". At the same time, some principal limitations of OOP had been noted. For example, the Circle-ellipse problem is difficult to handle using OOP's concept of inheritance.

However, Niklaus Wirth (who popularized the adage now known as Wirth's law: "Software is getting slower more rapidly than hardware becomes faster") said of OOP in his paper, "Good Ideas through the Looking Glass", "This paradigm closely reflects the structure of systems 'in the real world', and it is therefore well suited to model complex systems with complex behaviours" (contrast KISS principle).

Steve Yegge and others noted that natural languages lack the OOP approach of strictly prioritizing things (objects/nouns) before actions (methods/verbs). This problem may cause OOP to suffer more convoluted solutions than procedural programming.

OOP and control flow:

OOP was developed, to increase the reusability and maintainability of source code. Transparent representation of the control flow had no priority and was meant to be handled by a compiler. With the increasing relevance of parallel hardware and multithreaded coding, developer transparent control flow becomes more important, something hard to achieve with OOP.

Responsibility- vs. data-driven design:

Responsibility-driven design defines classes in terms of a contract, that is, a class should be defined around a responsibility and the information that it shares. This is contrasted by Wirfs-Brock and Wilkerson with data-driven design, where classes are -defined around the data-structures that must be held. The authors hold that

Attempts to find a consensus definition or theory behind objects have not proven verysuccessful (however, see Abadi & Cardelli, A Theory of Objects for formal definitionsof many OOP concepts and constructs), and often diverge widely. For example, somedefinitions focus on mental activities, and some on program structuring. One of thesimpler definitions is that OOP is the act of using "map" data structures or arrays thatcan contain functions and pointers to other maps, all with some syntactic andscoping sugar on top. Inheritance can be performed by cloning the maps (sometimescalled "prototyping"). OBJECT: = >> Objects are the run time entities in an object-oriented system. They may represent a person, a place, a bank account, a table ofdata or any item that the program has to handle. • •

1.3 OOP languages:Simula (1967) is generally accepted as the first language to have the primary features of an object-oriented language. It was created for making simulation programs, in which what came to be called objects were the most important information representation. Smalltalk(1972 to 1980) is arguably the canonical example, and the one with which much of the theory of object-oriented programming was developed. Concerning the degree of object orientation, the following distinctions can be made:

• Languages called "pure" OO languages, because everything in them is treated consistently as an object, from primitives such as characters and punctuation, all the way up to whole classes, prototypes, blocks, modules, etc. They were designed specifically to facilitate, even enforce, OO methods. Examples: Eiffel, Emerald., JADE, Obix, Scala, Smalltalk

• Languages designed mainly for OO programming, but with some procedural elements. Examples: C++, Java, C#, VB.NET, Python.

• Languages that are historically procedural languages, but have been extended with some OO features. Examples: Visual Basic(derived from BASIC), Fortran, Perl, COBOL 2002, PHP, ABAP.

• Languages with most of the features of objects (classes, methods, inheritance, reusability), but in a distinctly original form. Examples: Oberon (Oberon-1 orOberon-2) and Common Lisp.

« Languages with abstract data type support, but not all features of object-orientation, sometimes called object-based languages. Examples: Modula-2 (with excellent encapsulation and information hiding), Pliant, CLU.

OOP in dynamic languages:

In recent years, object-oriented programming has become especially popular in dynamic programming languages. Python, Ruby andGroovy are dynamic languages built on OOP principles, while Perl and PHP have been adding object oriented features since Perl 5 and PHP 4, and ColdFusion since version 5. The Document Object Model of HTML, XHTML, and XML documents on the Internet have bindings to the popular JavaScript/ECMAScriptlanguage. JavaScript is perhaps the best known prototype-based programming language, which employs cloning from prototypes rather than inheriting from a class.

Another scripting language that takes this approach is Lua. Earlier versions of ActionScript (a partial superset of the ECMA-262 R3, otherwise known as ECMAScript) also used a prototype-based object model. Later versions of ActionScript incorporate a combination of classification and prototype-based object models based largely on the currently incomplete ECMA-262 R4 specification, which has its roots in an early JavaScript 2 Proposal. Microsoft's JScript.NET also includes a mash-up of object models based on the same proposal, and is also a superset of the ECMA-262 R3 specification.

Design patterns:

Challenges of object-oriented design are addressed by several methodologies. Most common is known as the design patterns codified by Gamma et al.. More broadly, the term "design patterns" can be used to refer to any general, repeatable solution to a commonly occurring problem in software design. Some of these commonly occurring problems have implications and solutions particular to object-oriented development. Inheritance and behavioral subtyping

It is intuitive to assume that inheritance creates a semantic "is a" relationship, and thus to infer that objects instantiated from subclasses can always be safely used instead of those instantiated from the superclass. This intuition is unfortunately false in most OOP languages, in particular in all those that allow mutable objects. Subtype polymorphism as enforced by the type checker in OOP languages (with mutable objects) cannot guarantee behavioral subtyping in any context. Behavioral subtyping is undecidable in general, so it cannot be implemented by a program (compiler). Class or object hierarchies need to be carefully designed considering possible incorrect uses that cannot be detected syntactically. This issue is known as the Liskov substitution principle.

Gang of Four design patterns:

Design Patterns: Elements of Reusable Object-Oriented Software is an influential book published in 1995 by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, often referred to humorously as the "Gang of Four". Along with exploring the capabilities and pitfalls of object-oriented programming, it describes 23 common programming problems and patterns for solving them. As of April 2007, the book was in its 36th printing.

The book describes the following patterns:

• Creational patterns (5): Factory method pattern, Abstract factory pattern, Singleton pattern, Builder pattern, Prototype pattern

• Structural patterns (7): Adapter pattern, Bridge pattern, Composite pattern, Decorator pattern, Facade pattern, Flyweight pattern.Proxy pattern

• Behavioral patterns (11): Chain-Of-responsibility pattern, Command pattern, Interpreter pattern, iterator pattern, Mediator pattern,Memento pattern, Observer pattern. State pattern, Strategy pattern, Template method pattern, Visitor pattern...

Another scripting language that takes this approach is Lua. Earlier versions of ActionScript (a partial superset of the ECMA-262 R3, otherwise known as ECMAScript) also used a prototype-based object model. Later versions of ActionScript incorporate a combination of classification and prototype-based object models based largely on the currently incomplete ECMA-262 R4 specification, which has its roots in an early JavaScript 2 Proposal. Microsoft's JScript.NET also includes a mash-up of object models based on the same proposal, and is also a superset of the ECMA-262 R3 specification.

Design patterns:

Challenges of object-oriented design are addressed by several methodologies. Most common is known as the design patterns codified by Gamma et al.. More broadly, the term "design patterns" can be used to refer to any general, repeatable solution to a commonly occurring problem in software design. Some of these commonly occurring problems have implications and solutions particular to object-oriented development. Inheritance and behavioral subtyping

It is intuitive to assume that inheritance creates a semantic "is a" relationship, and thus to infer that objects instantiated from subclasses can always be safely used instead of those instantiated from the superclass. This intuition is unfortunately false in most OOP languages, in particular in all those that allow mutable objects. Subtype polymorphism as enforced by the type checker in OOP languages (with mutable objects) cannot guarantee behavioral subtyping in any context. Behavioral subtyping is undecidable in general, so it cannot be implemented by a program (compiler). Class or object hierarchies need to be carefully designed considering possible incorrect uses that cannot be detected syntactically. This issue is known as the Liskov substitution principle.

Gang of Four design patterns:

Design Patterns: Elements of Reusable Object-Oriented Software is an influential book published in 1995 by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, often referred to humorously as the "Gang of Four". Along with exploring the capabilities and pitfalls of object-oriented programming, it describes 23 common programming problems and patterns for solving them. As of April 2007, the book was in its 36th printing.

The book describes the following patterns:

• Creational patterns (5): Factory method pattern, Abstract factory pattern, Singleton pattern, Builder pattern, Prototype pattern

• Structural patterns (7): Adapter pattern, Bridge pattern, Composite pattern, Decorator pattern, Facade pattern, Flyweight pattern, Proxy pattern

• Behavioral patterns (11): Chain-Of-responsibility pattern, Command pattern, Interpreter pattern, Iterator pattern, Mediator pattern.Memento pattern, Observer pattern, State pattern, Strategy pattern, Template method pattern, Visitor pattern...

RSD-MUMBAI OBJECT ORIENTED PROGRAMMING WITH JAVA

Object-orientation and databases:

Both object-oriented programming and relational database management systems (RDBMSs) are extremely common in software today. Since relational databases don't store objects directly (though some RDBMSs have object-oriented features to approximate this), there is a general need to bridge the two worlds. The problem of bridging object-oriented programming accesses and data patterns with relational databases is known as Object-Relational impedance mismatch. There are a number of approaches to cope with this problem, but no general solution without downsides. One of the most common approaches is object-relational mapping, as found in libraries like Java Data Objects and Ruby on Rails' ActiveRecord.

There are also object databases that can be used to replace RDBMSs, but these have not been as technically and commercially successful as RDBMSs.

Real-world modeling and relationships:

OOP can be used to associate real-world objects and processes with digital counterparts. However, not everyone agrees that OOP facilitates direct real-world mapping (see Negative Criticism section) or that real-world mapping is even a worthy goal; Bertrand Meyerargues in Object-Oriented Software Construction that a program is not a model of the world but a model of some part of the world; "Reality is a cousin twice removed". At the same time, some principal limitations of OOP had been noted. For example, the Circle-ellipse problem is difficult to handle using OOP's concept of inheritance.

However, Niklaus Wirth (who popularized the adage now known as Wirth's law: "Software is getting slower more rapidly than hardware becomes faster") said of OOP in his paper, "Good Ideas through the Looking Glass", "This paradigm closely reflects the structure of systems 'in the real world', and it is therefore well suited to model complex systems with complex behaviours" (contrast KISS principle).

Steve Yegge and others noted that natural languages lack the OOP approach of strictly prioritizing things (objects/nouns) before actions (methods/verbs). This problem may cause OOP to suffer more convoluted solutions than procedural programming.

OOP and control flow:

OOP was developed, to increase the reusability and maintainability of source code. I Transparent representation of the control flow had no priority and was meant to be I handled by a compiler. With the increasing relevance of parallel hardware and I multithreaded coding, developer transparent control flow becomes more important, I something hard to achieve with OOP.

Responsibility- vs. data-driven design-.

Responsibility-driven design defines classes in terms of a contract, that is, a class I should be defined around a responsibility and the information that it shares. This is I contrasted by Wirfs-Brock and Wilkerson with data-driven design, where classes are defined around the data-structures that must be held. The authors hold that! resDonsibilitv-driven desien is preferable.

:

citicism:

A number of well-known researchers and programmers have analysed the utility of OOP. Here is an incomplete list:

• Luca Cardelli wrote a paper titled "Bad Engineering Properties of Object-Oriented Languages".

• Richard Stallman wrote in 1995, "Adding OOP to Emacsis not clearly an improvement; I used OOP when working on the Lisp Machine window systems, and 1 disagree with the usual view that it is a superior way to program." A study by Potok et al. has shown no significant difference in productivity between OOP and procedural approaches.

• Christopher J. Date stated that critical comparison of OOP to other technologies, relational in particular, is difficult because of lack of an agreed-upon and rigorous definition of OOP. Date and Darwen propose a theoretical foundation on OOP that uses OOP as a kind of customizable type system to support RDBMS.

• Alexander Stepanov suggested that OOP provides a mathematically limited viewpoint and called it "almost as much of a hoax asArtificial Intelligence. I have yet to see an interesting piece of code that comes from these OO people. In a sense, I am unfair to AI: I learned a lot of stuff from the MIT Al Lab crowd, they have done some really fundamental work....".

• Paul Graham has suggested that the purpose of OOP is to act as a "herding mechanism" that keeps mediocre programmers in mediocre organizations from "doing too much damage". This is at the expense of slowing down productive programmers who know how to use more powerful and more compact techniques.

-

• Joe Armstrong, the principal inventor of Erlang, is quoted as saying "The problem with object-oriented languages is they've got all this implicit environment that . they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."

• Richard Mansfield, author and former editor of COMPUTE! magazine, states that "like countless other intellectual fads over the years ("relevance", communism, "modernism", and so on—history is littered with them), OOP will be with us until eventually reality asserts itself. But considering how OOP currently pervades both universities and workplaces, OOP may well prove to be a durable delusion. Entire generations of indoctrinated programmers continue to march out of the academy, committed to OOP and nothing but OOP for the rest of their lives." He also is quoted as saying "OOP, is to writing a program,.what going through airport securityis to flying".

• Steve Yegge, making a roundabout comparison with Functional programming,writes, "Object Oriented Programming puts the Nouns first and foremost. Whywould you go to such lengths to put one part of speech on a pedestal? Whyshould one kind of concept take precedence over another? It's not as if OOP hassuddenly made verbs less important in the way we actually think. It's a strangelyskewed nersnective."

Rich Hickey, creator of Clojure, described object systems as over simplistic models of the real world. He emphasized the inability of OOP to model time properly, which is getting increasingly problematic as software systems become more concurrent.

• Carnegie-Mellon University Professor Robert Harper in March 2011 wrote: "Thissemester Dan Licata and I are co-teaching a new course on functionalprogramming for first-year prospective CS majors... Object-orientedprogramming is eliminated entirely from the introductory curriculum, because itis both anti-modular and anti-parallel by its very nature, and hence unsuitable fora modern CS curriculum. A proposed new course on object-oriented designmethodology will be offered at the sophomore level for those students who wishto study this topic."

1.4 Object-Oriented Programming Concepts: If you've never used an object-oriented programming language before, you'll need to learn a few basic concepts before you can begin writing any code. This lesson will introduce you to objects, classes, inheritance, interfaces, and packages. Each discussion focuses on how these concepts relate to the real world, while simultaneously providing an introduction to the syntax of the Java programming language.

What Is an Object?

An object is a software bundle of related state and behavior. Software objects are often used to model the real-world objects that you find in everyday life. This lesson explains how state and behavior are represented within an object, introduces the concept of data encapsulation, and explains the benefits of designing your software in this manner.

What Is a Class?

A class is a blueprint or prototype from which objects are created. This section defines a class that models the state and behavior of a real-world object. It intentionally focuses on the basics, showing how even a simple class can cleanly modei state and behavior.

What Is Inheritance?

Inheritance provides a powerful and natural mechanism for organizing and structuring your software. This section explains how classes inherit state and behavior from their superclasses, and explains how to derive one class from another using the simple syntax provided by the Java programming language.

What Is an Interface?

An interface is a contract between a class and the outside world. When a class implements an interface, it promises to provide the behavior published by that interface. This section defines a simple interface and explains the necessary changes for any class that implements it.

OBJECT ORIENTED PROGRAMMING WITH JAVA » ?

What Is a Package?

A package is -a namespace for organizing classes and interfaces in a logical manner. Placing your code into packages makes large software projects easier to manage. This section explains why this is useful, and introduces you to the Application Programming Interface (API) provided by the Java platform.

Objects:

Objects are the central idea behind OOP. The idea is quite simple.

An object is a bundle of variables and related methods.

A method is similar to a procedure; we'll come back to these later.

The basic idea behind an object is that of simulation. Most programs are written with very little reference to the real world objects the program is designed to work with; in object oriented methodology, a program should be written to simulate the states and activities of real world objects. This means that apart from looking at data structures when modelling an object, we must also look at methods associated with that object, in other words, functions that modify the objects attributes.

A few examples should help explain this concept. First, we turn to any student's favourite pastime...

Drink!

Say we want to write a program about a pint of beer. If we were writing this program in Modula-2, we could write something like this:

TYPE BeerType = RECORD

BeerName: STRING;

VolumelnPints: REAL;

Colour: ColourType;

Proof: REAL;

PintsNeededToGetYouDrunk: CARDINAL;

END;

Now lets say we want to initialise a pint of beer, and take a sip from it. In Modula-2, we might code this as:

VAR MyPint:- BeerType;

BEGIN

(* Initialise (i.e. buy) a pint: *)

RSD-MUMBAi

OBJECT ORIENTED PROGRAMMING WITH JAVA

MyPint.BeerName := "Harp";

MyPint.VolumelnPints := 1.00;

(* Take a sip *)

MyPint.VolumelnPints := MyPint.VoiumelnPints - 0.1;

We have constructed this entire model based entirely on data types, that is i defined BeerType as a record structure, and gave that structure various names, e Name. This is the norm for procedural programming.

This is however, not how we look at things when we want to program using objec If you remember how we defined an object at the start of this section, you i remember that we must not only deal with data types, but we must also deal vi methods.

A method is an operation which can modify an objects behaviour. In other words, i something that will change an object by manipulating its variables.

This means that when we take a real world object, in this case a pint of beer, w we want to model it using computational objects, we not only look at the d structure that it consists of, but also all possible operations that we might wanl perform on that data. For our example, we should also define the following meth associated with the BeerType object:

• InitialiseBeer - this should allow us to give our beer a name, a volume, etc.

• GetVolume - to see how much beer we have left!

• Take_A_Sip - for lunchtime pints...

• Take_A_Gulp - for quick pints...

• Sink_Pint - for post exam pints...

There are loads more methods we could define - we might want a func GetBeerName to help us order another pint for example. Now, some definitions object variable is a single variable from an object's data structure, exampleBeerName is one of BeerType's object variables. Now the important bit f this section:

Only an object's methods should modify its variables: ;

There are a few exceptions, but we'll cover them much later. What this means in example is that unlike the Modula code, we cannot directly modify BeerTj variables - we cannot set BeerName to "Guinness" directly. We must use the obj methods to do this. In practice, what this means is that we must think very care when we define methods.

Say in the above example we discover when writing the main program, that we need to be able to take a drink of arbitrary size; we cannot do this with the above definition, we can only take a sip, a gulp etc. We must go back and define a new method associated with BeerType, say Take_Drink which will take a parameter representing the amount of beer we wish to drink.

Another Example:

We'll now deal with a real-life example which will help us understand some more object concepts. We will design an object to emulate a counter.

A counter is a variable in a program that is used to hold a value. If you don't know that then you shouldn't be reading this! To make things very simple, we'll assume that our counter has only three operations associated with it:

• Initialising the counter to a value

• Incrementing the counter by one

• Getting the current value of the counter

So, when we come' to implement the above using objects we will define three methods that do the above.

You may be thinking that we could implement this very simply in Modula-2 using definition and implementation modules obtaining the same results as if we used an object oriented language. Well, we nearly can:

DEFINITION MODULE Counter;

PROCEDURE InitialiseCounter(InitialValue: INTEGER);

PROCEDURE IncrementCounter;

PROCEDURE GetCounterValueO: INTEGER;

END Counter.

IMPLEMENTATION MODULE Counter;

VAR MyCounter: INTEGER;

PROCEDURE InitialiseCounter(InitialValue: INTEGER);

BEGIN

MyCounter := InitialValue;

END InitialiseCounter;

PROCEDURE IncrementCounter;

BEGIN

INC(MyCounter);

END IncrementCounter;

PROCEDURE GetCounterValue():

INTEGER; BEGIN

RETURN MyCounter;

END GetCounterValue;

BEGIN

MyCounter := 0;

END Counter.

Because Modula-2 is not object oriented, this will only satisfy one of the requirements for an object oriented language - encapsulation. This simply means that we have implemented information hiding, i.e. we cannot directly accessMyCounter from any module that imports Counter. But being object oriented means a lot more than just encapsulation, as we'll see...

Inheritance:

Another big word for a simple concept. To help explain inheritance, we'll go back to our beer example. Say we want to define a new class to represent a pint of an imported French beer. This class would have all the variables and methods of the normal beer class, but it would have the following additional information:

• A variable representing the price of the beer

• Two methods to set and get the price of the beer

(We need this information because we are students; everyone knows the price of Harp, but we would like to know the price of this expensive beer before we order it!) It would be rather tedious to define a new class, FrenchBeerType which had all the variables and methods ofBeerType plus the few extra we needed, instead, we can define FrenchBeerType to be a subclass of BeerType.

A subclass is a class definition which derives functionality from another class definition.

Wh?v this means is that we only need to define the additional information that the FrenchBeerType class has.

So, we create a new class, FrenchBeerType, and tell our compiler that it is a subclass of BeerType. In the class definition, we would include only the following information:

• A variable BeerPrice

• A method SetBeerPrice

• A method GetBeerPrice

We do not need to include any information about BeerName for example; all this is automatically inherited; This means that FrenchBeerType has all the attributes of BeerType plus a few additional ones. All this talk of beer...

Counters. Counters. Counters...

Back to the counter example then! The counter we had in the last section is fine for most counting purposes. But say in a program we require a counter that can not only be incremented, but can be decremented too. Since this new counter is so similar in behaviour to our previous counter, once again would be mad to define a brand new class with everything that Counter has plus a new method. Instead, we'll define a new class ReverseCounter that is a subclass of Counter. We'll do this in Java.

class ReverseCounter extends Counter

<

/public void DecrementCounter(void) {

MyCounter—;

}

}

The extends clause indicates the superclass of a class definition. A superclass is the "parent" of a subclass; in our beer analogy, BeerType is the superclass of FrenchBeerType, so if we were defining this in Java we would use class FrenchBeerType extends BeerType. We are simply saying that we want ReverseCounter to be a subclass ofCounter. In Java, when we define a brand new class that is not a subclass of anything (as we did when we defmedCounter) we use the superclass Object to indicate we want the default superclass.

We have defined ReverseCounter to be a subclass of Counter. This means that if we instantiate a ReverseCounterobject, we can use any method that the class Counter provided, as well as the new methods provided. For example, if i is an object of the ReverseCounter class, then we can both increment it and decrement it;i.IncrementCounter(); and i.DecrementCounter; respectively.

Inheritance is a powerful tool. Unlike our simple example, inheritance can be passed on from generation to generation; we could define a class SuperDuperReverseCounter for example, that is a subclass of ReverseCounter which could provide added variables or methods.

Bugs, bugs, bugs...

If you tried to compile the above example and found it wasn't compiling, don't worry! There is a semi-deliberate mistake left in the code, which 1 am very usefully going to use to stress a point.

When defining a class you must consider subclasses.

When we defined the Counter class we didn't even know what a subclass was, so we could be forgiven for breaking this rule. If we go back to how the class was defined:

class Counter extends Object {

private int MyCounter;________

}

We can see that the variable MyCounter is defined to be of type private. In Java, this means that the variable becomes very, very private indeed; in fact, it is only accessible from inside the class from which it is defined. It is not available to any other class, including its derived classes. So when we reference MyCounter from inside theReverseCounter the Java compiler will kick up a fuss, since we don't have access to that variable.

We should have realised at the time of writing the Counter class that subclasses might need to get at this variable too. To fix this, all we have to do is change the definition of MyCounter to:

protected int MyCounter;

A variable with a protected qualifier means that it can be accessed from within the class in which it is defined, as well as all subclasses of this class. This is appropriate in this case.

1.5 Relationships: You already investigate relationships between abstract data types and instances and describe them in your own words. Let's go in more detail here.

A-Kind-Of relationship

Consider you have to write a drawing program. This program would allow drawing of various objects such as points, circles, rectangles, triangles and many more. For each object you provide a class definition. For example, the point class just defines a point by its coordinates:

class Point {

attributes:

int x, y

methods:

setX(int newX)

getX()

setY(int newY)

getYO

} . -

You continue defining classes of your drawing program with a class to describe circles. A circle defines a center point and a radius:

class Circle

{ attributes:

int x, y,

radius »

methods:

setX(int newX)

getxo

setY(int newY)

getY()

setRadius(newRadius) getRadius() ) Comparing both class

definitions we can observe the following:

• Both classes have two data elements x and y. In the class Point these elements describe the position of the point, in the case of class Circle they describe the circle's center. Thus, x and y have the same meaning in both classes: They describe the position of their associated object by defining a point.

• Both classes offer the same set of methods to get and set the value of the two data elements x and y.

• Class Circle "adds" a new data element radius and corresponding access methods.

Knowing the properties of class Point we can describe a circle as a point plus a radius and methods to access it. Thus, a circle is "a-kind-of" point. However, a circle is somewhat more "specialized". We illustrate this graphically as shown in Figure 1.1.

Fig. l.i Illustration of "a-kind-of" relationship

In this and the following figures, classes are drawn using rectangles. Their name always starts with an uppercase letter. The arrowed line indicates the direction of the relation, hence, it is to be read as "Circle is a-kind-of Point."

■ s-A relationship

The previous relationship is used at the class level to describe relationships between two similar classes. If we create objects of two such classes we refer to their relationship as an "is-a" relationship.

Since the class Circle is a kind of class Point, an instance of Circle, say a circle, is a pointv'. Consequently, each circle behaves like a point. For example, you can move points in x direction by altering the value of x. Similarly, you move circles in this direction by altering their x value.

Figure 1.2 illustrates this relationship, in this and the following figures, objects are drawn using rectangles with round corners. Their name only consists of lowercase letters.

Fig. 1.2 Illustration of "is-a" relationship

Part-Of relationship:

You sometimes need to be able to build objects by combining them out of others. You already know this from procedural programming, where you have the structure or record construct to put data of various types together.

Let's come back to our drawing program. You already have created several classes for the available figures. Now you decide that you want to have a special figure which represents your own logo which consists of a circle and a triangle. (Let's assume, that you already have defined a class Triangle.) Thus, your logo consists of two parts or the circle and triangle are part-of your logo:

class Logo {

attributes:

Circle circle

Triangle triangle

Methods:

set(Point where) ) We

frustrate this in Figure 1.3.

Pig. 1.3 Illustration of "part-of' relationship

ttes-A reiatkwsl^p:

This relationship is just the inverse version of the part-of relationship. Therefore we can easily add this relationship to the part-of illustration by adding arrows in the other direction (Figure 1.4).

Inheritance:

With inheritance we are able to make use of the a-kind-of and is-a relationship. As described there, classes which are a-kind-of another class share properties of the latter. In our point and circle example, we can define a circle which inherits from point:

class Circle inherits from Point {

attributes:

int radius

methods:

setRadius(int newRadius)

getRadiusO

>

Class Circle inherits all data elements and methods from point. There is no need to define them twice: We just use already existing and well-known data and method definitions.

On the object level we are now able to use a circle just as we would use a point, because a circle is-a point. For example, we can define a circle object and set its center point coordinates:

Circle acircle

•circle.setX(l) /* Inherited from Point *7

acircle.setY(2)

acircle.setRadius(3) /* Added by Circle */

"is-a" also implies, that we can use a circle everywhere where a point is expected. For example, you can write a function or method, say move(), which should move a point in x direction:

move(Point apoint, int deltax) {

apoint. setX (apoint. getXO + deltax)

}

As a circle inherits from a point, you can use this function with a circle argument to move its center point and, hence, the whole circle.-

Circle acircle

move{acircle, 10) /* Move circle; by moving */

/* its center point */

Let's try to formalize the term "inheritance":

Definition (Inheritance) Inheritance is the mechanism which allows a class A to inherit properties of a class B. We say "A inherits from B"7 Objects of class .A thus have access to attributes and methods of class B without the need to redefine them. The following definition defines two terms with which we are able to refer to participating classes when they use inheritance.

Definition (Superclass/Subclass) If class A inherits from class B, then B is called superclass of A. A is called subclass of B. Objects of a subclass can be used where objects of the corresponding superclass are expected. This is due to the fact that objects of the subclass share the same behaviour as objects of the superclass.

In the literature you may also find other terms for "superclass" and "subclass". Superclasses are also called parent classes. Subclasses may also be called child classes or just derived classes.

Of course, you can again inherit from a subclass, making this class the superclass of the new subclass. This leads to a hierarchy of superclass/subclass relationships. If you draw this hierarchy you get an inheritance graph.

A common drawing scheme is to use arrowed lines to indicate, the inheritance relationship between two classes or objects. In our examples we have used "inherits-from". Consequently, the arrowed line starts from the subclass towards the superclass as illustrated in Figure 1.5.

In the literature you also find illustrations where the arrowed lines are used just the other way around. The direction in which the arrowed line is used, depends on how the corresponding author has decided to understand it.

*Anyway, within this tutorial the arrowed line is always directed towards the superclass.

In the following sections an unmarked arrowed line indicates "inherit-from".

Multiple Inheritance:

One important object-oriented mechanism is multiple inheritance. Multiple inheritance does not mean that multiple subclasses share the same superclass. It also doesnot mean that a subclass can inherit from a class which itself is a subclass of another class.

Multiple inheritance means that one subclass can have more than one superclass. This enables the subclass to inherit properties of more than one superclass and to "merge" their properties.

As an example consider again our drawing program. Suppose we already have a classString which allows convenient handling of text. For example, it might have a methodto append other text. In our program we would like to use this class to add text to thepossible drawing objects. It would be nice to also use already existing routines suchas move() to move the text around. Consequently, it makes sense to let a drawabletext have a point which defines its location within the drawing area. Therefore wederive a new class DrawableString which inherits properties from Point and String asillustrated in Figure 1.6. _________ _______

Fig, 1.6 Derive a drawable string which inherits properties ofPoint and String

In our pseudo language we write this by simply separating the multiple superclasses by comma:

class DrawableString inherits from Point, String {

attributes:

/* All inherited from superclasses */

methods:

/* All inherited from superclasses */

}

We can use objects of class DrawableString like both points and strings. Because a drawablestring is-a point we can move them around

DrawableString dstring

move(dstring, 10)

Since it is a string, we can append other text to them:

dstring.append("The red brown fox ...")

Now it's time for the definition of multiple inheritance:

Definition (Multiple Inheritance) If class A inherits from more than one class, ie. A inherits from Bl, B2, ..., Bn, we speak of multiple inheritance. This may introduce naming conflicts in A if at least two of its superclasses define properties with the same name. The above definition introduce naming conflicts which occur if more than one superclass of a subclass use the same name for either attributes or methods. For an example, let's assume, that class String defines a method setX() which sets the string to a sequence of "X" characters^. The question arises, what should be inherited by DrawableString? The Point, String version or none of them?

These conflicts can be solved in at least two ways:

• The order in which the superclasses are provided define which property will beaccessible by the conflict causing name. Others will be "hidden".

• The subclass must resolve the conflict by providing a property with the name andby defining how to use the ones from its superclasses.

The first solution is not very convenient as it introduces implicit consequences depending on the order in which classes inherit from each other. For the second case, subclasses must explicitly redefine properties which are involved in a naming conflict. A special type of naming conflict is introduced if a class D multiply inherits from superclasses B and C which themselves are derived from one superclass A. This leads to an inheritance graph as shown in Figure 1.7.

Fig. 1.7 A name conflict introduced by a shared superclass of superclasses used with multiple inheritance.

The question arises what properties class D actually inherits from its superclasses B and C. Some existing programming languages solve this special inheritance graph by . deriving D with

• the properties of A plus

• the properties of B and C without the properties they have inherited from A.

Consequently, D cannot introduce naming conflicts with names of class A. However,if B and C add properties with the same name, D runs into a naming conflict. Another possible solution is, that-D inherits from both inheritance paths. In this solution, D owns two copies of the properties of A: one is inherited by B and one byC. ' Although multiple inheritance is a powerful object-oriented mechanism the problems introduced with naming conflicts have lead several authors to "doom" it. As the result of multiple inheritance can always be achieved by using (simple) inheritance some object-oriented languages even don't allow its use. However, carefully used, under some conditions multiple inheritance provides an efficient and elegant way of formulating things.

Abstract Classes:

With inheritance we are able to force a subclass to offer the same properties like their superclasses. Consequently, objects of a subclass behave like objects of their superclasses.

Sometimes it make sense to only describe the properties of a set of objects without knowing the actual behaviour beforehand. In our drawing program example, each object should provide a method to draw itself on the drawing area. However, the necessary steps to draw an objects depends on its represented shape. For example, the drawing routine of a circle is different from the drawing routine of a rectangle.

Let's call the drawing method print(). To force every drawable object to include such method, we define a class DrawableObject from which every other class in our example inherits general properties of drawable objects:

abstract class DrawableObject {

attributes:

methods:

print()

}

We introduce the new keyword abstract here. It is used to express the fact that derived classes must "redefine" the properties to fulfill the desired functionality. Thus from the abstract class' point of view, the properties are only specified but not fully defined. The full definition including the semantics of the properties must be provided by derived classes. Now, every class in our drawing program example inherits properties from the general drawable object class. Therefore, class Point changes to:

class Point inherits from DrawabieObject {

attributes:

int x, y

methods;

setX(int newX)

getX()

setY(int newY)

getYO

print() /* Redefine for Point */

} .

We are now able to force every drawable object to have a method called print which should provide functionality to draw the object within the drawing area. The superclass of all drawable objects, class DrawabieObject, does not provide any functionality for drawing itself. It is not intended to create objects from it. This class • rather specifies properties which must be defined by every derived class. We refer to this special type of classes as abstract classes:

Definition (Abstract Class) A class A is called abstract class if it is only used as a superclass for other classes. Class A only specifies properties. It is not used to create objects. Derived classes must define the properties of A.

Abstract classes allow us to structure our inheritance graph. However, we actuallydon't want to create objects from them: we only want to express commoncharacteristics of a set of classes.

Exercises:

1. Inheritance. Consider the drawing program example again.

(a) Define class Rectangle by inheriting from class Point. The point should indicate the' upper left corner of the rectangle. What are your class attributes? What additional methods do you introduce?

(b) All current examples are based on a two-dimensional view. You now want to introduce 3D objects such as spheres, cubes or cuboids. Design a classSphere by using a class 3D-Point. Specify the role of the point in a sphere. What relationship do you use between class Point and 3D-Point?

(c) What functionality does move() provide for 3D objects? Be as precise as you can.

(d) Draw the inheritance graph including the following classes DrawabieObject, Point, Circle, Rectangle, 3D-Point and Sphere.

(e) Have a look at the inheritance graph of Figure 1.8.

Fig. 1.8 Alternative inheritance graph for classSphere.

A corresponding definition might look like this:

class Sphere inherits from Circle

( attributes:

int z /* Add third dimension */

methods:

setZfint newZ)

getZ<)

}

Give reasons for advantages/disadvantages of this alternative.

2. Multiple inheritance. Compare the inheritance graph shown in Figure 1.9 with that of Figure 1.7. Here, we illustrate that B and C have each their own copy ofA.

Fig. 1.9 Illustration of the second multiple inheritance semantics

What naming conflicts can occur? Try to define cases by playing with simple exampleclasses.

1.6 Generic Types:

We already know generic types from chapter 3 when we have talked about generic abstract data types. When defining a class, we actually define a user defined type. Some of these types can operate on other types. For example, there could be lists of apples, list of cars, lists of complex numbers of even lists of lists.

At the time, when we write down a class definition, we must be able to say that this class should define a generic type. However, we don't know with which types the class will be used. Consequently, we must be able to define the class with help of a "placeholder" to which we refer as if it is the type on which the class operates. Thus, the class definition provides us with a template of an actual class. The actual class definition is created once we declare a particular object. Let's illustrate this with the following example. Suppose, you want to define a list class which should be a generic type. Thus, it should be possible to declare list objects for apples, cars or any other type-template class List for T { attributes:

... /■* Data structure needed to implement */ /*

the list */ methods:

append(T element) T

getFirst() T getNextO

bool more() )

The above template class List looks like any other class definition. However, the first line declares List to be a template for various types. The identifier T is used as a placeholder for an actual type. For example, append() takes one element as an argument. The type of this element will be the data type with which an actual list object is created. For example, we can declare a list object for apples if a definition fot the type Apple exists:

List for Apple appleList

Apple anApple,

anotherApple

appleList.append(anotherApple)

appleList.append(anApple) <

The first line declares appleList to be a list for apples. At this time, the compiler uses the template definition, substitutes every occurrence of T with Apple and creates an ' actual class definition for it. This leads to a class definition similar to the one that follows:

class List {

attributes:

... /* Data structure needed to implement */

/* the list */

methods.:

append(App1e element)

Apple getFirstO

Apple getNextO

bool more()

}

This is not exactly, what the compiler generates. The compiler must ensure that we can create multiple lists for different types at any time. For example, if we need another list for, say pears, we can write:

List for Apple appleList

List for Pear pearList

In both cases the compiler generates an actual class definition. The reason why both do not conflict by their name is that the compiler generates unique names. However, since this is not viewable to us, we don't go in more detail here. In any case, if you declare just another list oT apples, the compiler can figure out if there already is an actual class definition and use it or if it has to be created. Thus,

List for Apple aList

List for Apple anotherList

will create the actual class definition for aList and will reuse it for anotherList. Consequently, both are of the same type. We summarize this in the following definition:

Definition (Template Class) If a class A is parameterized with a data type B, A is called template class. Once an object of A is created, B is replaced by an actual data type. This allows the definition of an actual class based on the template specified for A and the actual data type.

We are able to define template classes with more than one parameter. For example, directories are collections of objects where each object can be referenced by akey.

Of course, a directory should be able to store any type of object. But there are also various possibilities for keys. For instance, they might be strings or numbers. Consequently, we would define a template class Directory which is based on two type parameters, one for the key and one for the stored objects.

Static and Dynamic Binding:

In strongly typed programming languages you typically have to declare variables prior to their use. This also implies the variable's definition where the compiler reserves space for the variable. For example, in Pascal an expression like

var i : integer;

declares variable i to be of type integer. Additionally, it defines enough memory space to hold an integer value.

With the declaration we bind the name i to the type integer. This binding is true within the scope in which i is declared. This enables the compiler to check at compilation time for type consistency. For example, the following assignment will result in a type mismatch error when you try to compile it:

var i : integer;

i := ^string';

We call this particular type of binding "static" because it is fixed at compile time. Definition (Static Binding) If the type T of a variable is explicitly associated with its name N by declaration, we say, that N is statically bound to T. The association process iscalled static binding.

There exist programming languages which are not using explicitly typed variables. For example, some languages allow to introduce variables once they are needed:

... /* No appearance of i */

i := 123 /* Creation of i as an integer */

The type of i is known as soon as its value is set. In this case, i is of type integer since we have assigned a whole number to it. Thus, because the content of i is a whole number, the type of i is integer.

Definition (Dynamic Binding) If the type T of a variable with name N is implicitly associated by its content, we say, that N is dynamically bound to T. The association process is called dynamic binding.

Both bindings differ in the time when the type is bound to the variable. Consider the following example which is only possible with dynamic binding:

if someconditionO -= TRUE then

n := 123

else

— . ii i ' I'lHI'illlllilltaiUIIIIIMilllliS:

n := 'abc'

endif

The type of n after the if statement depends on the evaluation of somecondition(). If it is TRUE, n is of type integer whereas in the other case it is of type string.

1.7 Polymorphism: Polymorphism allows an entity (for example, variable, function or object) to take a variety of representations. Therefore we have to distinguish different types of polymorphism which will be outlined here.

The first type is similar to the concept of dynamic binding. Here, the type of a variable depends on its content. Thus, its type depends on the content at a specific time:

v := 123 /* v is integer */

... /* use v as integer */

v := 'abc' /* v "switches" to string */

... /* use v as string */

Definition (Polymorphism (1)) The concept of dynamic binding allows a variable to take different types dependent on the content at a particular time. This ability of a variable is called polymorphism. Another type of polymorphism can be defined for functions. For example, suppose you want to define a function isNullQ which returns TRUE if its argument is 0 (zero) and FALSE otherwise. For integer numbers this is easy:

boolean isNull(int i) {

if (i == 0) then

return TRUE

else

return FALSE

endif

}

However, if we want to check this for real numbers, we should use another comparison due to the precision problem:

boolean isNull(real r) {

if (r < 0.01 and r > -0.99) then

return TRUE

else

return FALSE

endif }

In both cases we want the function to have the name isNull. In programming languages without polymorphism for functions we cannot declare these two functions because the name isNull would be doubly defined. Without polymorphism for functions, doubly defined names would be ambiguous. However, if the language would take the parameters of the function into account it would work. Thus, functions (or methods) are uniquely identified by:

• the name of the function (or method) and

• the types of its parameter list.

Since the parameter list of both isNull functions differ, the compiler is able to figure out the correct function call by using the actual types of the arguments:

var i : integer

var r : real

i = 0

r - 0.0

• • •

if (isNull(i)) then ... /* Use isNull(int) */

if (isNull(r)) then ... /* Use isNull(real) */

Definition (Polymorphism (2)) If a function (or method) is defined by the combination of

•'■'.• its name and

• the list of types of its parameters

we speak of polymorphism. This type of polymorphism allows us to reuse the same nama for functions (or methods) as long as the parameter list differs. Sometimes this type of polymorphism is called overloading.

The last type of polymorphism allows an object to choose correct methods. Consider the function move() again, which takes an object of class Point as its argument. We have used this function with any object of derived classes, because the is^a relation holds.

Now consider a function displayO which should be used to display drawable objects. The declaration of this function might look like this:

display(DrawableObject o) {

o.print()

}

• We would like to use this function with objects of classes derived from DrawableObject:

Circle acircle

Point apoint

Rectangle arectangle '

display(apoint) /* Should invoke apoint.print () */

display(acircle) /* Should invoke acircle.print() */

display(arectangle) /* Should invoke arectangle.print() */

The actual method should be defined by the content of the object o of function display(). Since this is somewhat complicated, here is a more abstract example:

class Base {

attributes:

methods:

virtual foo()

barl>

)

class Derived inherits from Base { - .

attributes:

methods: virtual

foo() bar() >

demo(Base o)

{ o.foo{)

o.bar() ^>

Base abase Derived

aderived

Dcr\-»iru»*nAi"™' nmprT nuiPMTPn DPor.PAn/iMiMr: WITH TAVA

demo{abase)

demo(aderived)

In this example we define two classes Base and Derived. Each class defines two methods foo() and bar(). The first method is defined as virtual. This means that if this method is invoked its definition should be evaluated by the content of the object.

We then define a function demo() which takes a Base object as its argument. Consequently, we can use this function with objects of class Derived as the is-a relation holds. We call this function with a Base object and a Derived object, respectively.

Suppose, that foo() and bar() ara defined to just print out their name and the class in which they are defined. Then the output is as follows:

foot) of Base called.

bar() of Base called.

foo() of Derived called.

bar() of Base called.

Why is this so? Let's see what happens. The first call to demo() uses a Base object. Thus, the function's argument is "filled" with an object of class Base. When it is time to invoke method foo() it's actual functionality is chosen based on the current content of the corresponding object o. This time, it is a Base object.' Consequently,foo() as defined in class Base is called.

The call to bar{) is not subject to this content resolution. It is not marked as virtual. Consequently, bar() is called in the scope of class Base.

The second call to demo() takes a Derived object as its argument. Thus, the argument o is filled with a Derived object. However, o itself just represents the Basepart of the provided object aderived.

Now, the call to foo() is evaluated by examining the content of o, hence, it is called within the scope of Derived. On the other hand, bar() is still evaluated within the scope of Base.

Definition (Polymorphism (3)) Objects of superclasses can be filled with objects of their subclasses. Operators and methods of subclasses can be defined to be evaluated in two contextes:

1. Based on object type, leading to an evaluation within the scope of the superclass.

2. Based on object content, leading to an evaluation within the scope of the contained subclass.

The second type is called polymorphism.

Chapter 2 The C Programming Language

2.1 Introduction: Developed in the late 1970s, C gained an huge success due to the development of UNIX which was almost entirely written in this language [4]. In contrast to other high level languages, C was written by programmers for programmers. Thus it allows sometimes, say, weird things which in other languages such as Pascal are forbidden due to its bad influence on programming style. Anyway, when used with some discipline, C is as good a language as any other.

The comment in C is enclosed in /* ... */. Comments cannot be nested.

2.2 Data Types: Table 2.1 describes the built-in data types of C. The specified Size is measured in bytes on a 386 PC running Linux 1.2.13. The provided Domain is based on theSize value. You can obtain information about the size of a data type with the sizeof operator.

Variables of these types are defined simply by preceeding the name with the type:

■: .../ int an_int ;

float a_float;

■■'..-,' long long a_very^long_integer;

With struct you can combine several different types together. In other languages this is sometimes called a record:

struct date_s {

int day, month, year;

1 aDate;

The above definition of aDate is also the declaration of a structure called date_s. We can define other variables of this type by referencing the structure by name:

struct date_s anotherDate;We do not have to name structures. If we omit the name, we just cannot reuse it. j However, if we name a structure, we can just decfare it wftnout cferTnmg a variable-.

>- struct time_s {

int hour, minute, second;

);

We are able to use this structure as shown for another Date. This is very similar to a type definition known in other languages where a type is declared prior to the definition of a variable of this type.

Variables must be defined prior to their use. These definitions must occur before any statement, thus they form the topmost part within a statement block.

Statements

C defines all usual flow control statements. Statements are terminated by : semicolon ";". We can group multiple statements into blocks by enclosing them -curly brackets. Within each block, we can define new variables:

I

int i; /* Define a global i */

i = 1; /* Assign i the value 0 */

{ /* Begin new block */

int i; /* Define a local i */

i = 2; /* Set its value to 2 */

} • /* Close block */