You are on page 1of 36

Object Oriented Programming

Object Oriented Programming


Object Oriented Programming (OOP) is a term loosely applied to mean any kind of programming that uses a programming language with some object oriented constructs or programming in an environment where some object oriented principles are followed. At its heart, though, object oriented programming is a mindset which respects programming as a problem-solving dilemma on a grand scale which requires careful application of abstractions and subdividing problems into manageable pieces. Compared with procedural programming, a superficial examination of code written in both styles would reveal that object oriented code tends to be broken down into vast numbers of small pieces, with the hope that each piece will be trivially verifiable. OOP was one step towards the holy grail of software-re-usability, although no new term has gained widespread acceptance, which is why "OOP" is used to mean almost any modern programming distinct from systems programming, assembly programming, functional programming, or database programming. Modern programming would be better categorized as "multi-paradigm" programming, and that term is sometimes used. This book is primarily aimed at modern, multi-paradigm programming, which has classic object oriented programming as its immediate predecessor and strongest influence. Historically, "OOP" has been one of the most influential developments in computer programming, gaining widespread use in the mid 1980s. Originally heralded for its facility for managing complexity in ever-growing software systems, OOP quickly developed its own set of difficulties. Fortunately, the ever evolving programming landscape gave us "interface" programming, design patterns, generic programming, and other improvements paving the way for more contemporary Multi-Paradigm programming. While some people will debate endlessly about whether or not a certain language implements "Pure" OOPand bless or denounce a language accordinglythis book is not intended as an academic treatise on object oriented programming or its theory. Instead, we aim for something more pragmatic: we start with basic OO theory and then delve into a handful of real-world languages to examine how they support OO programming. Since we obviously cannot teach each language, the point is to illustrate the trade-offs inherent in different approaches to OOP.

Introduction
For an overview and history of Object Oriented programming OOP, please reference the Wikipedia article. The reader is expected to have a basic familiarity with programming in general, as we will give examples in a variety of languages. We will explain any non-obvious syntax in the discussion, although this is besides the point. The point is to give some indication of the flavor of the languages and some insight into the real-world application of OO ideas.

Overview
We will divide up OOP into two phases classic and modern. While this distinction is somewhat arbitrary, we believe it is instructive to consider OOP as it was practiced in the 1980s and early 1990s to demonstrate the motivation for more current practices. What is Classic OOP? Object oriented programming can be traced back to a language called Simula, and in particular Simula 67, which was popular during the 1960s. It was Simula that first instituted "classes" and "objects," leading to the term "object oriented" programming. By the early 1990s, enough experience had been gained with large OOP projects to discover some limitations. Languages such as Self, ideas like interface programming (also known as component or component-oriented programming), and methodologies such as generic programming were being developed in response to these difficulties. Although often derided by OOP purists, it was the standardization of C++ in 1998 including generic programming facilities that really ushered in the modern era of OOP, which we also refer to

Object Oriented Programming as Multi-Paradigm programming. This is largely due to the popularity of C++ and the genius of the STL demonstrating the utility of the new methodology to such a large audience.

Classic or Pure OOP


By 1980, Xerox had made Smalltalk available to outsiders, appropriately named Smalltalk-80. Unlike other early programming languages, Smalltalk was a complete environment rather than just a language, a characteristic it had in common with Lisp at the time. While Lisp machines were foreshadowing IDEs to come, Smalltalk was pioneering the GUI, ultimately influencing the development of the Macintosh computer. Meanwhile, while Xerox was developing Smalltalk during the 70s, the C language was becoming popular thanks to UNIX being largely written in C. Therefore, it was C an otherwise unlikely candidate that Bjarne Stroustrup fused with ideas from Simula to create "C with Classes" which was renamed to C++ in 1983. In 1985, unsatisfied with Smalltalk, C++, and various object systems being tacked onto Lisp dialects, Bertrand Meyer created Eiffel. Even though much more recent, Java essentially cloned vintage C++, and so we consider Smalltalk, vintage C++, Eiffel, and Java to be Classic OOP. The object systems tacked onto Lisp (eventually standardized as CLOS in 1994) produced a very different methodology. While we don't consider CLOS to be Classic OOP, it did influence modern OOP.

Modern OOP and Multi Paradigm Programming


Classic OOP developed a tendency to over-rely on a technique called "inheritance," and eventually programmers realized that they were using inheritance for many things that are conceptually distinct. Modern OOP basically incorporates these concepts, sometimes as language level features, sometimes through programmer practice. The goal largely being looser coupling, easier maintenance and reuse. Historically, David Ungar and Randall Smith completed their first working Self compiler in 1987, and by 1990 Sun Microsystems had picked up the project. While Self did not survive to really become a modern OOP language, it was a second generation OOP language. Then, in the early 1990s, Alexander Stepanov and Meng Lee pioneered generic programming and wrote early drafts of C++'s STL. This began a (still ongoing) trend of incorporating functional programming ideas into more traditional OOP environments, in a kind of reverse CLOS. Additionally, the early 1990s saw the development of CORBA and Microsoft's COM, which was a natural extension of the ideas that had led to the original Windows API. This interface or component programming was a natural extension of encapsulation a basic tenet of OOP, as we will see. All of these developments were aimed at further managing or reducing complexity. Since this was the original goal of OOP and these techniques are used in conjunction with classic OOP, we find it appropriate to consider them in a treatment on "OOP". Contemporary object oriented programming, therefore, tends to be rather distinct from classic object oriented programming. Particularly, getting used to which abstractions are the most useful for which problem types is more challenging now that there are more to choose from! In a now classic book, Gamma et. al. introduced Design Patterns which helped to synthesize a variety of OOP techniques as applied to very common problems.

Future of OOP
The future contains more standardization of functional programming techniques in OOP environments, particularly lambda expressions and closures, and more robust meta-programming constructs. Applying design patterns automatically through generic or meta programming techniques is an interesting area.

What is an "Object"?
Loosely, the term "object" is used to conjure up connections with real world objects like a chair or a guitar. Except that for software, only some simplified abstraction is used, designed specifically for the task at hand. While a real chair is composed of atoms and molecules and reacts to its environment based on the laws of physics and its atomic composition, a "chair object" will vary wildly depending on whether you're writing a game or a Point-of-Sale system

Object Oriented Programming for a furniture store. Approaching your problem from the perspective of the chair will not be as productive as approaching the chair from the perspective of your problem. In most of the languages used in this book, you will find that technically speaking (something akin to whistling 9600 baud, I understand), an object is "an instance of a class". Great, so what does that mean? Well, we can trace this idea all the way back to Plato and his Platonic Ideal. If you spent more time watching Bill and Ted's Excellent Adventure than reading Plato, the idea is that the concept of a chair is a separate entity from any particular chair. In other words, you can conceive of a chair in the abstract without thinking of any particular chair. In most OOP languages, this abstracted idea of a chair is called a class (from classification) and is a prototype or blueprint for actually making chairs. The act of making something from the blueprint is often called "instantiating," and the made thing is both an object and an instance of the class that served as a blueprint. As humans, we normally tend to do this in reverse we categorize objects we encounter. We can easily identify chair-like things we run into as being chairs; this classification is where we got the term "class" in the first place. It is easy to drift off into abstruse philosophical debates over objectness; in some areas like knowledge representation and computational ontology they are very relevant. However, for a computer programmer, it is only necessary to figure out what your application needs to know about and do with chairs. This can be a sufficiently difficult problem, it's usually not necessary to make it harder! If you're still fuzzy on the whole idea, consider a more technical explanation. Structs (structures), records, tables, and other ways of organizing related information predated object oriented programming. You may be familiar with something like the following Pascal code: TYPE chair = RECORD model weight height color END;

: : : :

integer; integer; integer; COLOR;

This doesn't actually create a chair variable, but defines what a chair variable will look like when you create one. You could proceed to create arrays of chairs and so forth, and as we hope you've discovered for yourself, this kind of thing is quite indispensable for keeping your programs understandable. Object oriented programming wants to push this advantage and milk it for every ounce of understandability, correctness, and simplicity it can. A fundamental problem solving technique is divide and conquer you just have to figure out how to partition your problem into sub-problems. OOP innovators realized that we already had figured out ways to partition the problem, and it was reflected in the way we organized our data, like above. If you looked at an application that had that chair RECORD in it, you would surely find lots of code for doing things with chairs (why else would you bother to define it?). So, if you were to extract all of that code from all over the application and put it together with the chair definition, the reasoning goes, you should have an easier time ensuring that: all chair code is correct all chair code is consistent with each other there's no duplicated chair code overall, you have less spaghetti because chair code is no longer tangled up with sofa code etc

So you take that chair definition and that code extracted from all over the application, and call that a class. Take a chair variable and call it an object, and you're off to the races. Since this is supposed to be a pragmatic book, let's look at our first example code, this time in Python code: class Chair: model = None

Object Oriented Programming height = None weight = None color = None def has_arms(self): return self.model % 2 # odd-numbered models have armrests This doesn't look terribly different from the Pascal example. The only difference is that class Chair now contains a has_arms method(Methods are functions that live within a class, and are usually used to process certain class specific data). Hopefully the purpose is fairly clear, so let me point out the important part: has arms is a calculated or inferred property--this information is not stored directly. In Python, you would use this class like so: c = Chair() c.model = 15 c.height = 40 c.weight = 10 c.color = 7 if c.has_arms: do_something else: do_other_thing Here, the "c" variable is an instance of the 'chair' Class, also known as a chair object. We initialize the properties like you would in Pascal (this will change later!) and do one thing if the chair has arms and something else if it doesn't. But we never initialized a "has_arms" property or anything of the like. Since part of the goal is for you to become syntax agnostic, we present this same example again in C++: class Chair { public: int model; int weight; int height; int color; bool has_arms() { return model % 2 ? true : false; } }; Chair c; c.model = 15; c.height = 40; c.weight = 10; c.color = 7; if (c.has_arms()) do_something();

Object Oriented Programming else do_other_thing(); Now, we would just like to mention that this is just the tip of the iceberg and this example is not representative of good style (in either language). There may seem like little purpose to making objects with so little functionality, and you could easily generate equivalent code that requires no new class: struct Chair { int model; int weight; int height; int color; } c; Chair c = {15, 40, 10, 7 }; if (c.model % 2) do_something(); else do_other_thing(); The purpose of this section is to help you understand the terms; we will delve more into the benefits in the sections on encapsulation, polymorphism, inheritance, and on and on. However, let us say that while the "low-level" way might seem shorter and simpler, the object oriented benefits accrue with program size and complexity. This is not surprising, as that's what OOP was designed for, but it does make simple examples hard to come by. So bear with us.

State Machines
If you are unfamiliar with state machines, we won't delve too deep into them, but we highly recommend you look into them more. It's good for your clarity of thought process. Pedantically speaking, state machines are somewhat complicated mathematical constructs, and there are many interesting results that can be derived using the mathematical notation. But that's not our interest. Our interest is two-fold: For one, state machines provide a clear graphical way to illustrate potentially complicated application logic. First, you identify what your possible states are. For example, a server might be IDLE, CONNECTED, BUSY, ERROR, etc. Then, you define all the possible inputs, ie messages that the client might send, and for each state diagram the server's response to each input. This helps promote thoroughness as you think about reactions to unanticipated messages in various states. Secondly, state machines are a standard tool with a relatively standard notation. There are tools and libraries that will automatically make code given some canonical state machine format as input. This is effectively what regular expression processors do. In object oriented programming, "objects" are sometimes implementations of state machines. State machines are a better conceptual underpinning for behavioral entities servers, regular expression processors, graphics engine, and virtual machines are all good examples of behavioral entities. A basic distinction between simple objects and behavioral entities is that simple objects do not change their behavior based on their value. In fact, we tend to refer to their value rather than state. Simple objects tend to be kept in collections and searched through, passed to and returned from functions, and in general act like values. String and Rectangle are classic examples. Later on, we'll discuss message passing as an abstraction of method invocation, and it may seem a little strange in the context of simple objects.

Object Oriented Programming If you are still having trouble with the concept of objects, download and play with BlueJ within hours of using that IDE.
[1]

6 , Most people "Get it"

Classes, Types, and Classic OOP


There are some books on OOP that will tell you that the cornerstones of object oriented programming are encapsulation, inheritance, and polymorphism, or something along those lines. This is fairly typical of the classic OOP view, and there's nothing wrong with it per-se, it's just that we've generalized some ideas and decoupled things here and there since then.

Simple Objects vs Behavioral Entities


There are two fundamentally different types of objects, created and designed with different purposes in mind, using different techniques. We label these two types "Simple Objects" and "Behavioral Entities," although these labels are our own. Simple objects tend to represent values, like colors, coordinates, vectors, strings, etc, while behavioral entities tend to represent system components like services, message queues, engines, application logic, etc. Simple objects, if they own anything, are just wrapping what they own (like a system level handle). Usually, however, simple objects are untied to anything else, have no complicated startup or shutdown, and have little overhead. Simple objects tend to demand high performance, guaranteed correctness, discourage incorrect usage, are put in collections, searched, passed around, and generally manipulated by the rest of the program. Writing good simple objects, combined with good collection libraries provided by your language of choice, can easily reduce the complexity of basic operations by as much as 80%. Simple objects tend to focus on the encapsulation side of OOP rather than fancy message passing, as it's usually not a helpful abstraction to think of simple objects sending or receiving messages. Behavioral entities tend to maintain their state in various collections of simple objects, like a server keeping a list of logged in users. Behavioral entities tend to focus on behavior (to state the obvious), and configuring or tailoring that behavior in various circumstances. Message passing mechanisms, including polymorphism, tend to be central to the construction of behavioral entities. As a result, you tend to get whole families of similar entities, for example, an FTP server, an ssh server, an HTTP server, etc. that all have common functionality (like accepting connections). One of the primary forces behind OOP is separating out all of the common elements from these families and writing it once. This has obvious advantages in debugging and maintenance: you only have to fix bugs in common code once. Obviously, this is just abstraction at work but OOP gives you a well understood set of tools to do it with. Some languages features are tailored for one or the other. For example, operator overloading is truly important for simple objects, but mostly irrelevant for behavioral entities.

Encapsulation
Encapsulation is about risk management, reducing your maintenance burden, and limiting your exposure to vulnerabilities especially those caused by bypassed/forgotten sanity checks or initialization procedures, or various issues that may arise due to the simple fact of the code changing in different ways over time. Technically, encapsulation is hiding internal details behind an opaque barrier so as to force external entities to interact through publicly available access points. Think about it in the context of an OS kernel, like the Linux kernel. In general, you don't want a common user level application modifying any internal kernel data structures directly you want applications to work through the application programming interface or "API". Hence encapsulation is the general term we use for giving varied levels of separation between any core system elements and any common application elements. Otherwise, "unencapsulated code" would be bad for a number of obvious reasons:

Object Oriented Programming Applications could easily set invalid or nonsensical values, causing the whole system to crash. Forcing the application to use the API ensures that sanity checks get run on all parameters and all data structures maintain a consistent state. Internal data structures could be updated and change (even drastically so) between seemingly minor kernel updates. Sticking to the API insulates application developers from having to rewrite their code all the time. Applications could be used to "snoop" on each other, elevate their privileges, hog system resources, and violate any number of security protocols if they could directly manipulate kernel data structures. Application developers need little or no understanding of the Linux kernel to access kernel data. The random number engine illustrates this well. It can be accessed through /dev/random instead of wading through kernel structures, and you still get the same data. There are more, surely you can think of some. You may be thinking, "This is supposed to be about object oriented programming. I don't want to be a kernel developer!" Yes, we know, but the software kernel is the perfect example for discussing encapsulation, even though the kernel possesses no object oriented code itself. Encapsulation does not strictly apply to OOP, but it is used most within it. All the kernel's internal data its message queues, its process lists, its filehandles, etc. are all encapsulated inside the kernel, and cannot be seen outside the kernel. To work with the kernel, you must use its public interface, the API. For all the same reasons, writing your code in this way pertains the same benefits, even for writing a small app like a text editor or a mail client. Encapsulation, since its entire purpose is to hide details and restrict access, makes us consider exactly how access is restricted. It also makes us consider what exactly is a detail that needs to be protected, and what exactly should be exposed to the outside world. Figuring out what to expose, and especially at what granularity, is something of an art and we'll talk about it more in the section on interfaces. We'll move on to access restrictions, which come in two basic kinds: compile time and run time. Encapsulation is nothing but a combining code and data as a single unit. It is achieved by using the class concept, e.g.: class addition { int a,b; public: void read() { cout<<"\n Enter two numbers"; cin>>a>>b; } void print() { cout<<"\n first number:"<<a; cout<<"\n Second number:"<<b; } int cal() { return a+b; } } In the above example we are combining data(a and b) and the methods (read(),print(),cal())in to a single unit called by addition. Now we can access those methods by using objects.

Object Oriented Programming

Compile Time Enforced Access Restrictions


Many OOP languages have keywords along the lines of "public", "private" and "protected". These three were used by C++ in particular and have been oft copied since. They are used to group class members into three different levels of access: Public: Part of the public interface, anybody can access this member. Private: An internal detail, only members of this class may access this member. Protected: An internal detail also available to descendants of this class. As you can see, this is not the most flexible framework for controlling access. C++ also has a "friend" keyword to allow certain exceptions to access restrictions, but other problems persist. One common problem results from single classes that grow very large: sometimes you want access restricted to a subset of a classes functions. Alternatively, many generic frameworks like serialization or persistence need access to "private" data members. Unfortunately, there is no way to differentiate between "implementation detail" and "secret information". These kinds of language-level keywords only serve to prevent programs that violate these restrictions from compiling (and most scripting languages are compiled to some intermediate form these days). If somebody used a modified compiler that ignored these access restrictions (or in some languages just used some casting tricks), there is generally nothing to prevent a determined programmer from getting around these barriers.

Runtime Enforced Access Restrictions


Depending on the chip architecture in use, or possibly on the virtual machine running the byte code, it is sometimes possible to put "protected" information into areas of memory that will generate exceptions if read from, written to, or both. This allows for a program to abort or take other action if encapsulation is violated.

Accessors and Virtual (or Calculated) Properties


Accessors are just functions that set or return properties of an object. All too often, you'll see this kind of code in Java: class Dummy { private int val; public int GetVal() { return val; } public void SetVal(int val) { this.val = val; } } In this case, GetVal and SetVal are accessors, or "accessor functions". Java promotes lots of gratuitous accessors, and it often looks like unnecessary bloat. Sometimes it is. But often, people miss the point of encapsulation. If Dummy is well thought out, then Val is conceptually a property of Dummy. The fact that in this case that property is kept as a couple of bytes in memory is besides the point for anybody using a "Dummy". Even more importantly, users of Dummies are protected from any changes to how Val is calculated. All too often, the writer of a Dummy class is one himself, and Val has no logical or conceptual significance, and the accessors just get in the way.

Object Oriented Programming

"State" is Evil!
Something that we don't see reiterated enough: State (as opposed to change) is evil! Or, (perhaps better said) maintaining unnecessary state is the root of all (er... many) bugs. Let's look at an example, now in Ruby: # # # # We're displaying something over time, so we're dealing with both pixels and seconds. Based on the zoom level, there is a correlation between them: pixels per second, or PPS.

class Timeline { PPS; current_position_in_seconds; current_position_in_pixels; public: GetPosInSeconds() {current_position_in_seconds;} SetPosInSeconds(s) {current_position_in_seconds = s;} # oops, we're out of sync GetPosInPixels() {current_position_in_pixels;} SetPosInPixels(p) {current_position_in_pixels = p;} #oops, we're out of sync }

In this example, we're maintaining gratuitous state which is to say, we're holding the position in both seconds AND pixels. This is convenient, and important for users of this class, but we've messed up the encapsulation here. Whenever you set the value in one unit, you've destroyed the correctness for the other unit. Okay, you say, here's a simple fix: # # # # We're displaying something over time, so we're dealing with both pixels and seconds. Based on the zoom level, there is a correlation between them: pixels per second, or PPS.

class Timeline { PPS; current_position_in_seconds; current_position_in_pixels; public: GetPosInSeconds() {current_position_in_seconds;} SetPosInSeconds(s) { current_position_in_seconds = s; current_position_in_pixels = s*PPS; } GetPosInPixels() {current_position_in_pixels;} SetPosInPixels(p)

Object Oriented Programming { current_position_in_pixels = p; current_position_in_seconds = p/PPS; } } This fixes the obvious error with the previous example, but you've created a lot of work for yourself. Now you have to keep every calculation in every method in the Timeline class duplicated to maintain consistency. There could be dozens more where this came from (trust me). And what about when you add in other units, say inches? You have to duplicate all of that again. Presumably, you see where this is heading: calculated properties, logical properties, virtual properties, whatever you like to call them. Let's see this example again: class Timeline { PPS; # Pixels Per Second IPS; # Inches Per Second current_position_in_seconds; public: GetPosInSeconds() {current_position_in_seconds;} SetPosInSeconds(s) {current_position_in_seconds = s;} GetPosInPixels() {current_position_in_seconds*PPS;} SetPosInPixels(p) {current_position_in_seconds = p/PPS; } GetPosInInches() {current_position_in_seconds*IPS;} SetPosInInches(i) {current_position_in_seconds = i/IPS; } } Now, we're presuming that the conversion factors of PPS and IPS are set correctly for simplicity, but otherwise we've vastly simplified our problem. In twenty other functions we now write, we only have to worry about seconds, there's no consistency problems to worry about. Additionally, if we need to change our base units from seconds to pixels, the Timeline users need never know.

10

Inheritance
In many books, inheritance and OOP are made to seem synonymous, so it may seem strange that we deferred this discussion so far. This is a reflection of the diminished role of inheritance over time. In fact, one of the primary distinctions between Classic and Modern OOP lies in the usage of inheritance. As the old adage goes, if all you have is a hammer, then everything looks like a nail. And so it happened that often times, inheritance was the only tool available to the erstwhile OOP programmer, and so every concept under the sun (or at least the ghostly glow of a CRT) was crammed into inheritance. This lack of conceptual integrity and separation of concerns led to over-intimate dependencies and many difficulties. In some languages, programmer technique evolved to make the concepts clearer using the same limited language functions, while other languages explicitly developed features to address these concerns. Because you are almost certain to be exposed to some of this misguided advice at some point in your OOP learning, we'll try and explain some of the problems to you. However, much of the discussion will go in the sections where they properly belong! First off, though, what is inheritance? Well, just like when your grandma dies and you inherit that gawd-awful ugly lamp, inheritance in OOP grants the child-class (or derived-class) all of the attributes of the parent (or super) class.

Object Oriented Programming So, for example(in C++): class Parent { public: int f() {return 10;} }; class Child : public Parent { // see, nothing here! But wait, we inherited the function f()! }; Child c; int result = c.f();

11

// huh?

Oh, f() was inherited from the parent!

Is-A vs Has-A Moley Baloney


The most over-used and rather worthless discussion on inheritance that you will see revolves around the "Is-A vs Has-A" discussion. For example, a car is-a vehicle but has-a steering wheel. The idea these authors are chasing is that your car class should inherit your vehicle class and have a steering wheel as a member. You might also run across examples with shapes, where a Rectangle is-a Shape. The point is, once again, abstraction. The goal is to identify operations that operate only on the abstract notion of vehicle or shape and then write that code only once. Then, through the magic of inheritance, you can pass in cars or rectangles or what-have-you to the generic code, and it will work, since the derived classes are everything the parent classes are, "plus more". The problem here is that inheritance is mixing together several things: you inherit "typeness," interface, and implementation all at the same time. However, all of the examples focus on interface while talking about "typeness". The abstract code doesn't care that a car "is-a" vehicle, just that the objects respond to a certain set of functions, or interface. In fact, if you want to give your chair class accelerate(), brake(), turn_left() and turn_right() methods, shouldn't the abstract code be able to work on chairs then? Well, of course, but that doesn't make chairs vehicles. The kinds of solutions proposed in these "is-a" discussions have thus been mostly replaced by so-called "interface" programming and template programming. Since template programming offers the loosest coupling, it focused some attention on the syntactic-semantic confusion. Just because you have functions with the proper names, does that mean that they do what you think they do? If a chair class has accelerate(), brake() and other vehicle type methods, does it make sense to have generic vehicle code work on this chair? This led to more codifying of the assumptions of generic code: say, brake(INFINITY) ==> STOPPED. This implies that brake(x) != accelerate(-x). So a chair may make a better vehicle than the Starship Enterprise!

Delegation and "Dynamic Inheritance"


You will see more about delegation later in the section on message passing, but we wanted to mention that many problems solved by delegation are often tackled by inheritance in languages that don't offer a delegation feature. It's easier to show an example than explain, so in short, here's what delegation looks like:
interface I { int f(); } class A implements I

Object Oriented Programming


{ // A member variable that actually services all requests for // calls to the I interface. delegate I private_i; A(I target) { private_i = target; } } class B implements I { int f() { return 1; } } B b; // create a B object to be the target of A's delegation // Create an A object, passing in b // This call to f() is delegated to b.f(), causing 1 to be returned.

12

A a(b);

int foo = a.f();

Inheritance accomplishes a similar feat class B { int f() { return 1; } } class A inherits B { } A a; int foo = a.f(); // returns 1 just like in the delegation example.

However, the delegate can change over time, whereas base classes cannot. As a result, sometimes delegation is referred to as "dynamic inheritance".

Object Oriented Programming

13

Multiple Inheritance
Multiple inheritance is where an object inherits its properties from many different classes. For example, a house is both a "building" and a "place to sleep in". In multiple inheritance, an object inherits its properties from many objects (its parents or base classes). Therefore, we need to set up some classes, which we will use C++ for: class Building { int size; int purpose; int price; }; class PlaceToSleepIn { int type; // tent, house, dorm, etc. bool pleasant_to_live_in; // true or false }; In C++, to inherit all the types, one uses the : operator, like so: class House : public Building, public PlaceToSleepIn { // all of the Building and PlaceToSleepIn variables are here! int rooms; // the number of rooms }; Looking at other popular languages : Multiple Inheritance is not a feature of Java, where as it is very much used in C++ and Python[citation needed].

Problems with Inheritance


One problem of Inheritance is that users of predefined classes may not know the location of the abstracted data. Therefore, it may not be easy for them to obtain it. Another major problem with inheritance in large programs is called Fragile Base Class. An example could be of an attribute that was declared in the base class as byte but later turns out to need the range of word. Changing this to word will necessitate at least recompiling all sub-classes but that might well not be enough because the sub-classes might have relied on the type of this attribute so that the source code also will need to be changed.

Object Oriented Programming

14

Separation of Static and Dynamic


Systems Architecture The Benefits of Static Analysis
Dealing With Hierarchies

Traditional Neglect of Dynamic Analysis

Messages, Protocols and Dispatch


Delegation

Interfaces
Introduction
An Interface allows a class to expose a different set of properties and methods depending on context. For example, say that you were writing a Visual Basic 2005 application that manages clients. A client could be an individual person, or an organization. Part of the program generates address labels for clients. You might define a person like this: Class Person Public LastName As String Public FirstName As String Public Address As String End Class You might also define an Organization like this: Class Organization Public Name As String Public MailingAddress As String Public BuildingAddress As String End Class As you can see, the main differences between a Person and an Organization are: a Person has both a first name and a last name, while an organization has only a single name an Organization has a separate mailing address, while a Person only has one address So that you can have the one routine to print address labels, you create an interface called "IAddressLabel" (by convention, the name of an interfaces should start with a capital I). Interface IAddressLabel ReadOnly Property Name() As String ReadOnly Property Address() As String End Interface

Object Oriented Programming You now change the Person class to implement this interface. The main thing to notice is that the Person's first and last names are combined on the label.
Class Person Implements IAddressLabel Public LastName As String Public FirstName As String Public Address As String Public ReadOnly Property Address1() As String Implements IAddressLabel.Address Get Return Address End Get End Property Public ReadOnly Property Name() As String Implements IAddressLabel.Name Get Return FirstName & " " & LastName 'combine the first and last names for the address label End Get End Property End Class

15

You now change the Organization class to implement the IAddressLabel interface. Notice that the address for the label is the mailing address, not the building address.
Class Organization Implements IAddressLabel Public Name As String Public MailingAddress As String Public BuildingAddress As String Public ReadOnly Property Address() As String Implements IAddressLabel.Address Get Return MailingAddress 'Use the mailing address for the address label End Get End Property Public ReadOnly Property Name1() As String Implements IAddressLabel.Name Get Return Name End Get End Property End Class

Now you can group the disparate objects together as a collection of address labels!
Sub Main() 'create a person object Dim Bill As New Person Bill.FirstName = "William" Bill.LastName = "Jones" Bill.Address = "123 Test Rd Testville 9123" 'create another person object Dim Sally As New Person

Object Oriented Programming


Sally.FirstName = "Sally" Sally.LastName = "Smith" Sally.Address = "999 Sample Ave Testburg 9222" 'create an Organization object Dim WidgetsInc As New Organization WidgetsInc.Name = "Widgets Incorporated" WidgetsInc.BuildingAddress = "9123 Avenue Rd Sampletown 9876" WidgetsInc.MailingAddress = "P.O. Box 123 Sampletown 9876" 'Because all three objects implement the IAddressLabel interface, we can put them in the same array Dim MailingList(2) As IAddressLabel MailingList(0) = Bill MailingList(1) = Sally MailingList(2) = WidgetsInc 'loop through, displaying the address label for each object Dim i As Integer For i = 0 To 2 MsgBox(MailingList(i).Name & vbCrLf & MailingList(i).Address) Next i End Sub

16

Interfaces vs. Inheritance


Interfaces and Inheritance can both be used to solve the problem of treating dissimilar objects collectively. For example, if you have a Cat class and a Dog class, but have some routine that needs to process them together, you could either: Create an Animal base class, which contains procedures common to both Cats and Dogs, and have Cat and Dog inherit from Animal, or Create an IAnimal interface, and have both Cat and Dog implement the interface. Which approach to use depends on several factors. In general: If you are extending an existing class, then use inheritance. For example, if you already have an Animal class, and then discover a need to distinguish between Cats and Dogs If you are simply wanting to treat different objects as the same, then use Interfaces. For example, you already have Cat and Dog classes, and then discover a need to manipulate them in a similar fashion

Delegation
Inheritance vs Delegation

Lifetime Management
Factories
In the real world, factories are used to make stuff (e.g. automobiles). In OO programming, factories also make stuff; specifically, OO factories "make" (instantiate) objects. At least in Java, a constructor is unable to return a reference to an existing object--it MUST return a brand-new object. This can cause two problems--too many object instances, and identical objects that are duplicates--not the exact same object.

Object Oriented Programming Factories are generally implemented as a public static method inside a class that has only private constructors. In this way, only the factory can create instances "Guaranteeing*" that all instances of the object have been created by the factory. The factory most often has an internal "Cache" of objects. Whenever a user asks the factory for a new object, the cache is consulted first and one of the cached objects are returned if it is identical--otherwise a new instance is created, added to the cache and returned. Factories can also be used to inject user code into an "Unmodifiable" library. It is possible to save and restore a user object that implements some important functions of a library object. The library then uses that factory to get instances of the users object, and doesn't even know that the user has replaced a core component with completely new code. As an example... Say the library uses Library objects all over the place. The library user can create a class (let's call it User) that extends Library. The then call LibraryFactory.set(User.class), and the factory stores it. Inside the library, whenever the library wishes to use a Library object, it calls the LibraryFactory.Factory() function to get a new instance. Without changing any code, the user can now completely change the way the library functions by overriding one or more methods in his User class. This is used in various places inside the Java SDK to allow you to change how chunks of the SDK works without rewriting any of the code. In Java, just having private constructors does not truly guarantee that all your objects came from the factory, serialization and reflection can still create new instances without going through the constructor.

17

Garbage Collection
Garbage collection refers to freeing of heap-allocated memory. The heap memory must be freed eventually. Either the programmers code must explicitly free it, or some automatic system mechanism is required. The most common mechanism is mark and sweep. This is where the system knows of certain top-level classes (Threads and windows mostly). It follows all the references from these "Known" classes to every class that can be reached and marks each class. When it's done, it "sweeps" (gets rid of) every unmarked class. Garbage Collection is a huge enabler of OO development--it completely changes the way you design. With code-based memory management it is necessary to have some way to track an object. If it is created on the stack, it will be deleted when the method exists (so instances passed outside your method will become invalid). If it is created on the heap, some object must delete it manually--so if your method is going to create an object and pass it to two other objects that both retain the object, you have a problem. Who deletes the object? The original method can't because it will have exited before the two objects are finished with it, and the two objects shouldn't know anything about each other. This type of problem is often solved with "Reference counting" which is another form of garbage collection, but a manual one. It also leads to fewer long-lived, free-roaming classes being created since they have to be tracked. GC solves problem, that of ownership. If you are programming in a language with Garbage Collection, you may create classes on the fly, pass them off, retain a copy or forget about it... You really can't go wrong. When all instances have been "Forgotten", the class disappears. The drawback is that GC tends to take a solid chunk of time. This is less true lately as at least Java has threaded GC and the ability to limit the amount of time GC will run. There are actually dozens of tuning and reporting options and the ability to select from multiple GC systems to fit your need. GC Implementations run from trivial (instance counting) to amazingly complex. The current default Java VM uses a multi-tiered system with different mechanisms for new, middle-aged and old objects. For instance, since almost all new objects tend to die almost instantly, the first section (Eden) is divided in half. When one half becomes full, the currently referenced objects are copied to the other side. The system switches to using the "new" side and completely

Object Oriented Programming forgets about the old half. There is no explicit code invoked to delete objects that are already gone. This means that GC can actually be more efficient than traditional allocation/free since there is no free operation for nearly all objects. Garbage collection should be considered essential to OO Design.

18

Persistence
Persistence is simply the act of having objects that "Stick around" between invocations of your program. This can be trivial (Just serializing an object out when exiting, serializing it back in when loading) to a full OO-database implementation. Hibernate is a good program that sits between your application and a database and ensures that your objects are properly persisted.

Serialization
Serialization is converting an object to a stream of bytes that can then be saved to a file or transmitted over a network.

Generic Programming
Abstracting Classes
In this article along with the demo project I will discuss Interfaces versus Abstract classes. The concept of Abstract classes and Interfaces is a bit confusing for beginners of Object Oriented programming. Therefore, I am trying to discuss the theoretical aspects of both the concepts and compare their usage. And finally I will demonstrate how to use them with C#.

Design Patterns
Gang of Four/Background Reasons/Benefits What it isn't Different groups/people have different names Examples: observer decorator facade strategy

Model-View-Controller (MVC)
The 'model-view-controller pattern is an architectural pattern used primarily in creating graphic user interfaces ("GUIs"). The major premise of the pattern is based on modularity and it is to separate three different aspects of the GUI, the; the data (model), the visual representation of the data (view), and the interface between the view and the model (controller). The primary idea behind keeping these three components separate is so that each one is as independent of the others as possible, and changes made to one will not affect changes made to the others. In this way, for instance, the GUI can be updated with a new look or visual style without having to change the data model or the controller.

Object Oriented Programming

19

Model
Generally, the model is constructed first. This doesn't necessarily need to be anything special, it's just an object the way you would normally make an object, with properties that can be configured and queried using getters and setters. The important thing to remember about the model is that every property that is going to show up in the view needs to support property listeners. This will allow the controller to update the view when the model changes.

View
This can often be constructed after the model. Frequently, each property in the model will have it's own component in the GUI, called an "editor". Certain property types often have standard associated editor types. For instance, a property whose value in an unconstrained text string might be a text field, or a text box. Numeric properties will often use a text field as well, but in this case, the controller will need to do some checking on the entered value to make sure it is really a number. Properties with a small predefined set of allowed values will often use a combo box to allow the users to select one of the predefine values. More complex properties will likely require more complex editors. Like the model, the view will generally need to support listeners so that the controller can update the model based on the user input. Different languages handle this in different ways. Some languages allow callback functions to be associated with editors, which get called when the value is changed. Other languages allow you to add listeners directly to the component, which can be notified when the value in the editor changes, or when it's clicked on, or when it looses focus, etc.

Controller
The controller frequently isn't an actual object, but a collection of methods and listeners, often built in to both the model and the view. The general pattern is that both the model and the view have a certain interface which provide accessibility to their data values or editor respectively. For instance, for a property called "Title", the model may have methods "getTitle" and "setTitle", while the view might have "setTitleFieldText" and "getTitleFieldText". Alternatively, the view may simply provide accessor methods to its editor components directly, so you might instead have "getTitleField().setText()" and "getTitleField().getText()". The controller is then designed to "plug into" each of these interfaces, and pass data between them. When the controller is notified through one of it's listeners that either the model or the view has changed, it may validate the new value (particularly if the value if coming from the view) and then pass it along to the other component. Validation When possible, it's usually best to allow the model to do all the necessary validation of values, so that any changes to the allowed values, or changes simply to the validation process, only need to be made in one place. However, in some languages under certain circumstances, this may not be possible. For instance, if a numeric property is being edited with a text field, then the value of the property passed to the controller by the view will be text, not a number. In this case, the model could be made to have an additional method that takes text as the input value for this property, but more likely, the controller will do the initial parsing of the text to get the numeric value, and then pass it on to the model to do further validation (for instance, bounds checking). When either the controller or the model determines that a passed in value is invalid, the controller will need to tell the view that the value is invalid. In some cases, the view may then issue an error dialog or other notification, or it may simply revert the value in it's editor to the older valid value.

Object Oriented Programming

20

Visitor Pattern
The visitor pattern is something like a variation on the Iterator pattern except it allows even more encapsulation. The purpose is to provide a way of performing a certain operation (function, algorithm, etc) for each element in some sort of collection of elements. The basic premise is that you have a Visitor interface with a method named visit which take one argument, and the collection has a method (typically named foreach) which takes a Visitor as the argument. This method of the collection will use some encapsulated way of stepping through each of it's elements, and for each element, it will invoke the Visitors's visit method, passing as the argument the current element. This process is essentially equivalent to getting the collection's iterator, and using a while(iterator.hasNext()) loop to invoke visitor.visit(iterator.next()). The key difference is that the collection can decide exactly how to step through the elements. If you're familiar with iterators, you may be thinking that the iterator can decide how to step through, too, and the iterator is usually defined by the collection, so what's the difference? The difference is that the iterator is still bound to a while loop, visiting each element in succession, one at a time. With the visitor pattern, the collection could conceivably create a separate thread for each element and have the visitor visiting them concurrently. That's just one example of ways that the collection may decide to vary the method of visitation in a manner that can't be mimicked by an iterator. The point is, it's encapsulated, and the collection can implement the pattern in what ever way it feels is best. More importantly, it can change the implementation at any time, without affecting client code, because the implementation is encapsulated in the foreach method.

An Example implementation of Visitor Pattern: String


To illustrate a simple implementation of visitor pattern, let's imagine we're reinventing Java's String class (it'll be a pretty ridiculous reinvention, but it'll be good for this exercise). We're not going to implement very much of the class, but let's assume that we're storing a set of chars that make up the string, and we have a method called getCharAt which takes an int as it's only argument, and returns the character at that position in the string, as a char. We also have a method called length which takes no arguments, and returns an int which gives the number of characters in the string. Let's also assume that we want to provide an implementation of the visitor pattern for this class which will take an instance that implements the CharacterVisitor interface (which we'll define, below), and calls it's visit method for each character in the string. First we need to define what this CharacterVisitor interface looks like: public interface CharacterVisitor { public void visit(char aChar); } Easy enough. Now let's get down to our class, which we'll call MyString, and it looks something like this: public class MyString { //... other methods, fields //Our main implementation of the visitor pattern public void foreach(CharacterVisitor aVisitor){ int length = this.length(); //Loop over all the characters in the string for (int i=0; i<length; i++){ //Get the current character, and let the visitor visit it.

Object Oriented Programming aVisitor.visit(this.getCharAt(i)); } } //... other methods, fields }//end class MyString So that was pretty painless. So what can we do with this? Well let's make a class called MyStringPrinter, which prints an instance of MyString to the standard output.
class MyStringPrinter implements CharacterVisitor { //We have to implement this method because we're implementing the CharacterVisitor //interface public void visit(char aChar){ //All we're going to do is print the current character to the standard output System.out.print(aChar); } //This is the method you call when you want to print a string public void print(MyString aStr){ //we'll let the string determine how to get each character, and // we already defined what to do with each character in our // visit method. aStr.foreach(this); } }//end class MyStringPrinter

21

That was simple too. Of course, it could've been a lot simpler,right? We didn't need the foreach method in MyString, and we didn't need MyStringPrinter to implement the visitor, we could have just used the MyString classes getCharAt and length methods to set up our own for loop ourselves and printed each char inside the loop. Well sure you could, but what if MyString isn't MyString but instead is MyBoxOfRocks. In a box of rocks, is there a set order that the rocks are in? Unlikely. Of course MyBoxOfRocks has to store the rocks somehow. Maybe it stores them in an array, and there is actually a set order of the rocks, even if it is artificially introduced for the sake of storage. On the other hand, maybe it doesn't. The point is once again, that's an implementation detail that you as the client of MyBoxOfRocks shouldn't have to worry about, and should never rely on. Presumably, MyBoxOfRocks wants to provide someway for clients to get at the rocks inside it. It could, once again, introduce an artificial order to the rocks; assign each rock an index an provide a method like public Rock getRock(int aRockNumber). Or maybe it wants to put names on all the rocks and let you access it like public Rock getRock(String aRockName). But maybe it's really just a box of rocks, and there's no names, no numbers, no way of identifying which rock you want, all you know is you want the rocks. Alright, let's try it with the visitor pattern. First out visitor interface (assume Rock is already defined somewhere, we don't care what it is or what it does): public interface RockVisitor { public void visit(Rock aRock); }

Object Oriented Programming Easy. Now out MyBoxOfRocks public class MyBoxOfRocks { private Rock[] fRocks; //... some kind of instantiation code public void foreach(RockVisitor aVisitor){ int length = fRocks.length; for (int i=0; i<length; i++){ aVisitor.visit(fRocks[i]); } } }//end class MyBoxOfRocks Huh, what do you know, it does store them in an array. But what do we care now? We already wrote the visitor interface, and all we have to do now is implement it in some class which defines the actions to take for each rock, which we would have to do inside a for loop anyway. Besides, the array is private, our visitor doesn't have any access to that. And what if the implementor of MyBoxOfRocks did a little homework and found out that comparing a number to zero is infinitesimally faster than comparing it to a non zero. Infinitesimal, sure, but maybe when you're iterating over 10 million rocks, it makes a difference (maybe). So he decides to change the implementation: public void foreach(RockVisitor aVisitor){ int length = fRocks.length; for (int i=length-1; i>=0; i--){ aVisitor.visit(fRocks[i]); } } Now he's iterating backwards through the array and saving a (very) little time. He's changed the implementation because he found a better way. You didn't have to worry about finding the best way, and you didn't have to change you code because the implementation is encapsulated. And that's not the half of it. Maybe a new coder takes control of the project, and maybe this coder hates arrays and decides to totally change it: public class MyBoxOfRocks { //This coder really likes Linked Lists private class RockNode { Rock iRock; RockNode iNext; RockNode(Rock aRock, RockNode aNext){ this.iRock = aRock; this.iNext = aNext; } }//end inner class RockNode

22

Object Oriented Programming

23

private RockNode fFirstRock; //... some instantiation code goes in here //Our new implementation public void foreach (RockVisitor aVisitor){ RockNode current = this.fFirstRock; //a null value indicates the list is ended while (current != null){ //have the visitor visit the current rock aVisitor.visit(current.iRock); //step to the next rock current = current.iNext; } } Now maybe in this instance, linked lists were a poor idea, not as fast as a nice lean array and a for loop. On the other hand, you don't know what else this class is supposed to do. Maybe providing access to the rocks is only a small part of what it does, and linked lists fit in better with the rest of the requirements. In case I haven't said it enough yet, the point is that you as the client of MyBoxOfRocks don't have to worry about changes to the implementation, the visitor pattern protects you from it. I have one more trick up my sleeve. Maybe the implementor of MyBoxOfRocks notices that a lot of visitors are taking a really long time to visit each rock, and it's taking far too long for the foreach method to return because it has to wait for all visitors to finish. He decides it can't wait that long, and he also decides that some of these operations can probably be going on all at once. So he decides to do something about it, namely, this: //Back to our backward-array model public void foreach(RockVisitor aVisitor){ Thread t; //this should speed up the return int length = fRocks.length; for (int i=length-1; i>=0; i--){ final Rock curr = fRocks[i] t = new Thread(){ public void run(){ aVisitor.visit(curr); } }; //end anonymous Thread class t.start(); //run the thread we just created. current = current.iNext; } }

Object Oriented Programming If you're familiar with threads, you'll understand what's going on here. If you're not, I'll quickly summarize: a Thread is basically something that can run "simultaneously" with other threads on the same machine. They don't actually run simultaneously of course, unless maybe you have a multi-processor machine, but as far as Java is concerned, they do. So for instance, when we created this new Thread called t, and defined what happens when the Thread is run (with the run method, naturally), we can then start the Thread a-running and it will start running, splitting cycles on the processor with other Threads, right away, it doesn't have to wait for the current method to return. Likewise, we can start it running and then continue on our own way immediately, without waiting for it to return. So with the above implementation, the only time we need to spend in this method is the time it takes to instantiate all the threads, start them running, and loop over the array; we don't have to wait for the visitor to actually visit each Rock before we can loop, we just loop right away, and the visitor does it's thing on whatever CPU cycles it can swipe. The whole visiting process might take just as long (maybe even longer if it looses some cycles because of the multiple threads), but the thread from which foreach was invoked doesn't have to wait for it to finish, it can return from the method and be on it's way much faster. If you're confused about the use of the final Rock called curr in the above code, it's just a bit of a technicality for using anonymous classes: they can't access non final local variables. Even though fRocks doesn't fit into this category (it's not local, it's an instance variable), it i does. If you tried to remove this line an simply put fRocks[i] in the run method, it wouldn't compile. So what happens if you're the visitor, and you decide that you need to visit each rock one at a time? There's a number of reasons this might happen such as if your visit method changes your instance variables, or maybe it depends on the results of previous calls to visit. Well the implementation inside the foreach method is encapsulated from you, you don't know if it's using separate threads or not. Sure you could figure it out with some fancy debugging, or some clever printing to std out, but wouldn't it be nice if you didn't have to? And if you could be sure that if they change it in the next version, your code will still work properly? Well fortunately, Java provides the 'synchronize mechanism, which is basically an elaborate device for locking up blocks of code so that only one Thread can access them at a time. This won't conflict with the interests of the multi-threaded implementation, either, because the locked out thread still won't block the thread that created them, they'll just sit and wait patiently, only blocking code on itself. That's all well beyond the scope of this section, however, but be aware that it's available and probably worth looking into if you're going to be using synchronicity-sensitive visitors.

24

Factory Pattern
Intro to the Factory Pattern
The factory pattern is a design pattern used to promote encapsulation of data representation. It's primary purpose is to provide a way for users to retrieve an instance with a known compile-time type, but whose runtime type may actually be different. In other words, a factory method that is supposed to return an instance of the class Foo may return an instance of the class Foo, or it may return an instance of the class Bar, so long as Bar inherits from Foo. The reason for this is that it strengthens the boundary between implementor and client, hiding the true representation of the data (see Abstraction Barrier) from the user, thereby allowing the implementor to change this representation at anytime without affecting the client, as long as the client facing interface doesn't change.

Object Oriented Programming

25

Basic Implementation of the Factory Pattern


The general template for implementing the factory pattern is to provide a primary user facing class with static methods which the user can use to get instances with that type. Constructors are then made private/protected from the user, forcing them to use the static factory methods to get objects. The following Java code shows a very simple implementation of the factory pattern for type Foo.
public class Foo {

//Static factory method public static Foo getInstance(){ //inside this class, we have access to private methods return new Foo(); }

//guarded constructor, only accessible from within this class, since it's marked private private Foo(){ //typical initialization code goes here }

}//end class Foo

With this code, it would be impossible for a client of the code to use the new operator to get an instance of the class, as is traditionally done: //Client code Foo f = new Foo();

//Won't Work!

because the constructor is makred private. Instead, the client would have to use the factory method: //Client code Foo f = Foo.getInstance();

//works!

It should be noted that even within a programming language community, there is no general consensus as to the naming convention of a factory method. Some suggest naming the method with the name of the class, similar to a normal constructor, but starting with a lowercase. Others say that this is confusing, and suggest using an accessor type syntax, like the getInstance style used above, though others complain that this may incorrectly imply a singleton implementation. Likewise, some offer newInstance, but this is criticized as being misleading in certain situations where a strictly new instance may not actually be returned (once again, refer to the singleton pattern). As such, we will not attempt to follow any particularly rigid standard here, we will simply try to use a name that makes the most sense for our current purposes.

Object Oriented Programming

26

Factory Pattern Implementation of the Alphabet


That's great, you know how to implement a real simple factory pattern, but what good did it do you? Users are asking for something that fits into type Foo, and they're getting an instance of the class Foo, how is that different from just calling the constructor? Well it's not, except that you're putting another function call on the stack (which is a bad thing). But that's only for the above case. We'll now discuss a more useful use of the factory pattern. Consider a simple type called Letter, representing a letter in the alphabet, which has the following client facing interface (i.e., public instance methods): char toCharacter(); boolean isVowel(); boolean isConsonant(); We could implement this easily enough without using the factory method, which might start out something like this: public class Letter { private char fTheLetter; public Letter(char aTheLetter){ fTheLetter = aTheLetter; } public char toCharacter(){ return fTheLetter; } public boolean isVowel(){ //TODO: we haven't implemented this yet return true; }

public boolean isConsonant(){ //TODO: we haven't implemented this yet return false; } }//end class Letter Fairly simple, but notice we haven't implemented the last two methods yet. We can still do it pretty easily. The first might look like this: public boolean return fTheLetter fTheLetter fTheLetter fTheLetter isVowel(){ == == == == 'a' 'e' 'i' 'o' || || || ||

Object Oriented Programming fTheLetter fTheLetter fTheLetter fTheLetter fTheLetter fTheLetter } Now that's not too bad, but we still need to do isConsonant. Fortunately, we at least know in this case that if it's a vowel, it's not a consonant, and vice versa, so our last method could simply be: public boolean isConsonant(){ return !this.isVowel(); } So what's the problem here? Basically, everytime you call either of these methods, your program has to do all that checking. Granted, this isn't a real heavy burden for the Java Runtime Environment, but you can imagine a much more complex, much more time consuming operation. Wouldn't it be great if we could avoid doing this everytime we call the method? Let's say, for instance, we could do it once when we create the object, and then not have to do it again. Well sure, we can do that. Here's an implementation that'll do that for us, and we still don't have to use the factory method: public class Letter { private char fTheLetter; private boolean fIsVowel; public Letter(char aTheLetter){ fTheLetter = aTheLetter; fIsVowel = fTheLetter == 'a' || fTheLetter == 'e' || fTheLetter == 'i' || fTheLetter == 'o' || fTheLetter == 'u' || fTheLetter == 'A' || fTheLetter == 'E' || fTheLetter == 'I' || fTheLetter == 'O' || fTheLetter == 'U'; } public char toCharacter(){ return fTheLetter; } public boolean isVowel(){ return fIsVowel; } == == == == == == 'u' || 'A' || 'E' || 'I' || 'O' || 'U';

27

Object Oriented Programming

28

public boolean isConsonant(){ return !fIsVowel; } }//end class Letter Notice how we moved the lengthy operation into the constructor, and stored the result. Ok, so now we're all fine and dandy, no? Sure, but let's say you came up with a new idea, a different implementation: you want to split this type into two classes, one class to handle the vowels, and one to handle the consonants. Great, they can both be subclasses of the Letter class, and the user will never know the difference, right? Wrong. How is the client supposed to get at these new classes? They've got code that works perfectly well for them by calling new Letter('a') and new Letter('Z'). Now you're going to make them go through all their code and change these to new Vowel('a') and new Consonant('Z')? They probably won't be too happy with that. If only you could get new instances of both classes from one method! Well you can, just use a static method in the Letter class, it'll do the same one-time checking as the constructor did, and will return an appropriate instance of the right class. And what do you know, it's a factory method! But that still doesn't do your client much good, they still need to go through and change all the new Letter()s into Letter.getLetter(). Well, sad to say, it's too late to help them at all, unless you just give up your new implementation. But that illustrates the reason for using the factory method right off the bat. One of the key components of good object oriented programming is that you never know exactly where your code will go in the future. By making good use of the abstraction barrier and using encapsulation-friendly programming patterns, such as the factory pattern, you can better prepare yourself--and your client--for future changes to the specific implementation. In particular, it allows you to use a "big hammer" kind of approach to get something done in a perhaps-less-than-ideal but rapid manner in order to meet deadlines or move ahead with testing,. You can then go back later and refine the implementation--the data representation and algorithms--to be faster, smaller, or what-have-you, and as long as you maintained the abstraction barrier between implementor and client and properly encapsulated your implementation, then you can change it without requiring the client to change any of their code. Well now that I'm sure you're a raving advocate for the factory method, let's take a look at how we would implement it for our Letter type: public abstract class Letter { //Factory Method public static Letter getLetter(char aTheLetter){ //Like before, we do a one time check to see what kind of // letter we are dealing with. Only this time, instead of setting // a property to track it, we actually have a different class for each // of the two letter types. if ( aTheLetter == 'a' || fTheLetter == 'e' || fTheLetter == 'i' || fTheLetter == 'o' || fTheLetter == 'u' ||

Object Oriented Programming fTheLetter fTheLetter fTheLetter fTheLetter fTheLetter ){ return new } else{ return new } } == == == == == 'A' 'E' 'I' 'O' 'U' || || || ||

29

Vowel(aTheLetter);

Consonant(aTheLetter);

//User facing interface // We make these methods abstract, thereby requiring all subclasses // (actually, just all concrete subclasses, that is, non-abstract) // to implement the methods. public abstract boolean isVowel(); public abstract boolean isConsonant(); public abstract char getChar();

//Now we define the two concrete classes for this type, // the ones that actually implement the type. private static class Vowel extends Letter { private char iTheLetter; //Constructor Vowel(char aTheLetter){ this.iTheLetter = aTheLetter; } //Nice easy implementation of this method! public boolean isVowel(){ return true; } //This one, too! public boolean isConsonant(){ return false; }

Object Oriented Programming public char getLetter(){ return iTheLetter; } }//end local class Vowel

30

private static class Consonant extends Letter { private char iTheLetter; //Constructor Vowel(char aTheLetter){ this.iTheLetter = aTheLetter; } public boolean isVowel(){ return false; } public boolean isConsonant(){ return true; } public char getLetter(){ return iTheLetter; } }//end local class Consonant }//end toplevel class Letter Several things to note here. First, you'll notice the top level class Letter is abstract. This is fine because you'll notice that it doesn't actually do anything except define the interface and provide a top level container for the two other classes. However, it's also important (not just o.k.) to make this abstract because we don't want people trying to instantiate the Letter class directly. Of course we could solve this problem by making a private constructor, but making the class abstract instead is cleaner, and makes it more obvious that the Letter class is not meant to be instantiated. It also, as mentioned, allows us to define the user facing interface that the work horse classes need to implement. The two nested classes we created are called local classes, which is basically the same as an inner class except that local classes are static, and inner classes are not. They have to be static so that our static factory method can create them. If they were non static (i.e., dynamic) then they could only be accessed through an instance of the Letter class, which we can never have because Letter is abstract. Also note that (in Java, anyway) the fields for inner and local classes typically use the "i" (for inner) prefix, as opposed to the "f" (for field) prefix used by top level classes. This is simply a naming convention used by many Java programmers and doesn't actually effect the program. The two nested classes the implement the Letter data type do not actually have to be local/inner. They could just have easily been top level classes that extend the abstract Letter class. However, this is contrary to the point of the

Object Oriented Programming factory pattern, which is encapsulation. Top level classes can't be private in Java, because that doesn't make any sense (what are they private to?) and the whole point is that no client has to (or should, really) know how the type is implemented. Making these classes top level allows clients to potentially stumble across them, and worse yet, instantiate them, by-passing the factory pattern all together. Lastly, this is not very good code. There's a lot of ways we can make it better to really illustrate the power of the factory pattern. I'll discuss these refactorings briefly, and then show another, more polished, version of the above code which includes a lot of them. Refactoring the Factory Pattern Notice that both of the local classes do the same thing in a few places. This is redundant code which is not only more work to write, but it's also highly discouraged in object oriented programming (partially because it takes more work to write, but mostly because it's harder to maintain and prone to errors, e.g., you find a bug in the code and change it in one spot, but forget to in another.) Below is a list of redundancies in the above code: The field iTheLetter The method getLetter() The constructor of each inner class does the same thing. In addition, as we discovered above, the isVowel() and isConsonant() just happen to always return the opposite of eachother for a given instance. However, since this is something of a peculiarity for this particular example, we won't worry about it. The lesson you would learn from us doing that will already be covered in the refactoring of the getLetter() method. Ok, so we have redundant code in two classes. If you're familiar with abstracting proccesses, then this is probably a familiar senario to you. Often, having redundant code in two different classes makes them prime candidates for abstraction, meaning that a new abstract class is created to implement the redundant code, and the two classes simply extend this new abstract class instead of implementing the redundant code. Well what do you know? We already have an abstract super class that our redundant classes have in common. All we have to do is make the super class implement the redundant code, and the other classes will automatically inherit this implementation, as long as we don't override it. So that works fine for the getLetter() method, we can move both the method and the iTheLetter field up to the abstract parent class. But what about the constructors? Well our constructor takes an argument, so we won't automatically inherit it, that's just the way java works. But we can use the super keyword to automatically delegate to the super classes constructor. In otherwords, we'll implement the constructor in the super class, since that's where the field is anyway, and the other two classes will delegate to this method in their own constructors. For our example, this doesn't save much work, we're replacing a one line assignment with a one line call to super(), but in theory, there could be hundred of lines of code in the constructors, and moving it up could be a great help. At this point, you might be a little worried about putting a constructor in the Letter class. Didn't I already say not to do that? I thought we didn't want people trying to instantiate Letter directly? Don't worry, the class is still abstract. Even if there's a concrete constructor, Java won't let you instantiate an abstract class, because it's abstract, it could have method that are accessible but undefined, and it wouldn't know what to do if such a method was invoked. So putting the constructor in if fine. After making the above refactorings, our code now looks like this:
public abstract class Letter { //Factory Method

31

Object Oriented Programming


public static Letter getLetter(char aTheLetter){ if ( aTheLetter == 'a' || fTheLetter == 'e' || fTheLetter == 'i' || fTheLetter == 'o' || fTheLetter == 'u' || fTheLetter == 'A' || fTheLetter == 'E' || fTheLetter == 'I' || fTheLetter == 'O' || fTheLetter == 'U' ){ return new Vowel(aTheLetter); } else{ return new Consonant(aTheLetter); } }

32

//Our new abstracted field. We'll make it protected so that subclasses can see it, // and we rename it from "i" to "f", following our naming convention. protected char fTheLetter;

//Our new constructor. It can't actually be used to instantiate an instance // of Letter, but our sub classes can invoke it with super protected Letter(char aTheLetter){ this.fTheLetter = aTheLetter; }

//The new method we're abstracting up to remove redundant code in the sub classes public char getChar(){ return this.fTheLetter; }

//Same old abstract methods that define part of our client facing interface public abstract boolean isVowel(); public abstract boolean isConsonant();

Object Oriented Programming


//The local subclasses with the redundant code moved up. private static class Vowel extends Letter { //Constructor delegates to the super constructor Vowel(char aTheLetter){ super(aTheLetter); } //Still need to implement the abstract methods public boolean isVowel(){ return true; } public boolean isConsonant(){ return false; } }//end local class Vowel

33

private static class Consonant extends Letter { Consonant(char aTheLetter){ super(aTheLetter); } public boolean isVowel(){ return false; } public boolean isConsonant(){ return true; } }//end local class Consonant

}//end toplevel class Letter

Note that we made our abstracted field protected. This isn't strictly neccessary in this case, we could have left it private, because the subclasses don't actually need to access it at all. In general, I prefer to make things protected instead of private, since, as I mentioned, you can never really be sure where a project will go in the future, and you may not want to restrict future implementors (including yourself) unneccessarily. However, many people prefer to default to private and only use protected when they know it's neccessary. A major reason for this is the rather peculiar and somewhat unexpected meaning of protected in Java, which allows not only subclasses, but anything in the same package to access it. This is a bit of a digression, but I think it's a fairly important debate that a good Java programmer should be aware of.

Object Oriented Programming

34

The Factory Pattern and Parametric Polymorphism


The latest version of the Java Virtual Machine (5.0) has introduced something called Parametric Polymorphism, which goes by many other names in other languages, including "generic typing" in C++. In order to really understand the rest of this section, you should read that section first. But basically, this means that you can introduce additional parameters into a class--parameters which are set at instantiation--that define the types of certain elements in the class, for instance fields or method return values. This is a very powerful tool which allows programmers to avoid a lot of those nasty instanceofs and narrowing castes. However, the impelementation of this device in the JVM does not promote the use of the Factory pattern, and in the two do not play well together. This is because Java does not allow methods to be parameterized the way types are, so you cannot dynamically parameterize an instance through a method, only through use of the new operator. As an example, imagine a type Foo which is parameterized with a single type which we'll call T. In java we would write this class like this: class Foo<T> { }//end class Foo Now we can have instances of Foo parameterized by all sorts of types, for instance: Foo<String> fooOverString = new Foo<String>(); Foo<Integer> fooOverInteger = new Foo<Integer>(); But let's say we want to use the factory pattern for Foo. How do we do that? You could create a different factory method for each type you want to parameterize over, for instance: class Foo<T>{ static Foo<String> getFooOverString(){ return new Foo<String>(); } static Foo<Integer> getFooOverInteger(){ return new Foo<Integer>(); } }//end class Foo But what about something like the ArrayList class (in the java.util package)? In the java standard libraries released with 5.0, ArrayList is parameterized to define the type of the object stored in it. We certainly don't want to restrict what kinds of types it can be parameterized with by having to write a factory method for each type. This is often the case with parameterized types: you don't know what types users will want to parameterize with, and you don't want to restrict them, so the factory pattern won't work for that. You are allowed to instantiate a parameterized type in a generic form, meaning you don't specify the parameter at all, you just instantiate it the way you would have before 5.0. But that forces you to give up the parameterization. This is how you do it with generics: class Foo<T> { public static <E> Foo<E> getFoo(){ return new Foo<E>(); }

Object Oriented Programming

35

}//end class Foo

The Introduction of Functional Programming Ideas


Functions as "True Citizens" References
[1] http:/ / www. bluej. org/

Article Sources and Contributors

36

Article Sources and Contributors


Object Oriented Programming Source: http://en.wikibooks.org/w/index.php?oldid=2100713 Contributors: AdRiley, Adrignola, Albmont, Alexsmail, Arulgalaxy, Arunreginald, Augustus.saunders, BillKress, Bmearns, Dallas1278, Darklama, Derbeth, Derekhepworth, Einst3, Evan Chaney, Fidge43, Guanaco, Herbythyme, IO, Incubusaurus, Jguk, Jomegat, Kowey, Krischik, Kwhitefoot, Liblamb, Mike.lifeguard, Mkn, Mshonle, Paddu, Panic2k4, Pengrate, Psequeirag, QuiteUnusual, Recent Runes, Redlentil, Rimodo, Snaxe920, Spoon!, Surturz, Techman224, Thenub314, Tom Morris, Ubuprofaan, Vertigo, 216 anonymous edits

License
Creative Commons Attribution-Share Alike 3.0 Unported http:/ / creativecommons. org/ licenses/ by-sa/ 3. 0/

You might also like