Object Oriented Programming Philosophy

Part 1 -- Basic Understanding & Encapsulation





Introduction

I hope that I don't scare you with the term "philosophy". Well, forget about that. Welcome back! First of all I am very happy to write another tutorial. Because of the demand, I wrote this one. I think this one will fit nicely too in Java tutorial. OK.

Speaking the terms of "philosophy" means the deep understanding of something. Therefore, OOP philosophy here means (for me) a deep understanding of OOP. So, I hope, after following this tutorial, you will be able to see clearly the gems behind OOP. Why it is preferred by so many people and why it is said to be a better solution in solving things.

 

The Understanding

Hey, what does OOP mean? Yeah, we know its abbreviation, but what it is all about? It's a programming style that based its thinking into objects in the real world. That's how it got its name. In "normal" way in thinking programs, we usually think about the functionality of a program. It's like this: oh, this program calculate the degree of students. So, we usually divide the program based on its functionality, for example: We might build a procedure to get the students marks. Then, we build another function to determine calculate the final marks from that. Then we build a function to determine the grade of that particular final mark. And so on. This kind of habit severely infects our mind so that we cannot think into another perspective. These typical symptoms are usually suffered by imperative language programmers, i.e. Pascal / C programmers, etc. I was also infected by these contagious "virus" :-) but now I'm disinfected and immune to such disease. :-)

However, there is no easy way to get rid of the old mechanism of thinking and "reformat" it with a new perspective. It's kinda frustrating and somehow similar to "brainwashing". :-) I myself needed time to adjust into the new paradigm. Hmm... it's about 6 months, I believe. 1992, those memories.... :-) So, probably it will take you about such a long time of to adapt, too. Or probably yours will be shorter... I hope that this tutorial will help you shorten the learning time. No need to take another 6 months, right?

Now, how's the new paradigm work? First of all, we should determine the objective of the program. What is to be accomplished by the program you'd like to make. Try not to divide it as the functionality. Otherwise, you would fall into the pitfall I mentioned before. If you make a large project, try to think its general purpose as a whole first before dividing it.

Then, we should base our thinking in the objects rather than in terms of functionality. From our example above, rather than thinking the program that way, we should rethink the program in terms of the students (the subject), the marks, and the reports. See the difference? However, thinking this way is definitely not easy.

 

Encapsulation

After you think which objects are involved in your program, you should list the following:

Of course you should list the ones that is relevant to your program. You can list that students can play football, but that's nothing to do with grade report program. :-) Students do some exams? Ummm yes... but it's not relevant either. Since students are not active in determining the grade, we should think the other way. Aha! Students can receive the report. OK, so we would like to code something like this:

Student.Receive(Report);

That's a pseudocode. You don't have to worry about that first. OK, what else? Probably we should look into the values or properties. What values or properties are of the students and they are needed in reporting grade. Aha! That's easy, you said:

Enough for now. So, what is the relationship of these things anyway, you asked? Well, in OOP approach, we have to ENCAPSULATE the things that the object can do or the things that can be done to that object along with its conveying values or properties. That's encapsulation. Hurray, you now understand the first idiom of OOP!

In real world of programming, the things that the object can do or the things that can be done to that object are made into functions or procedures. These function and procedures are now called methods. The values or properties are usually stored into the variables of the object and they are called properties or fields. And the object itself is later called class. Classes can only have methods and fields.

The methods of the object usually process its own fields or, accessing the methods of another object passed into as a parameter. Like the Student.Receive(Report); above. The method Receive accept Report which is a class. Later on in the body of Receive method, it can access the methods of the Report class.

 

Instantiation

Like structures or records, those classes must be instantiated. What is the instantiation means? In structures, we have the definition of a structure and the variable of that structure as an instance. For example:

type
  pStudent = ^tStudent;
  tStudent = Object
                Name : string[30];
                ID   : longint;
                :
                :  { <--Snip--> }
                procedure Receive(Report r);
               end;
   :
   : { and so on, assuming the Report is defined elsewhere }
var
  std : tStudent;
  p   : pStudent;

We can observe that tStudent is the declaration of the class and std is the instance of that class. If we later add p := new (tStudent);, p^ will later be the instance of that class, too. So, the understanding here is significant. You have to understand what the instance means.

The methods within the classes works in the scope of instances. So, even std and p^ share the same class, they work with different set of data because std and p^ are different instances. So, it's different Name and different ID! std has its own scope and p^ has its own. They never interfere each other. Even when you invoked Receive, (i.e. std.Receive(x); and p^.Receive(x);) the method works differently in both instances as they have different sets of data.

And take note that the methods work in the scope of instances, not global! Never think that the fields Name and ID are just one for all classes. This is one of the difficulties of the programming paradigm. You can think that each field is instantiated, or created, when the new instance of that class is created. Thus, each instance  has its own fields, completely separated than that of the other instance of the same class.

 

Encapsulation Continued

Since the methods work within the spaces of instances, you should design classes and methods that way. Moreover, you can not access data from another instance even it is of the same class. There is a way in doing this, i.e. in Message Passing, but that will be discussed later.

One of the intention of the encapsulation is that to prohibit the unauthorized access of the fields. So, the fields inside the class can be accessed by that particular class (unless you specify the accessor keyword like public or private, but that will be discussed later). Therefore, we need to create accessor methods to access a particular field.

Typically, if the field is read and write accessible, we would like to define two accessor methods: get and set. For example, if we would like to make the Name field accessible from other instances, we would provide:

  procedure setName(newName: string);
  begin
    Name := newName;
  end;

  function getName: string;
  begin
    getName := Name;
  end;

That was seemingly very inefficient at the first glance, but it provides the protection of data that never been offered by usual imperative programming, i.e. it prohibits unauthorized access. For example, in set accessor, we might add some code to validate the data. Moreover, if you provide a read-only field, you just have to provide the get accessor. This way will make impossible for a program to accidentally write such fields. That similar reason also occurs for write-only field. Even, you can define fields that is internal to the instance, for example temporary variables or counters that have meanings only inside the instance. In that case, you don't need to provide any accessors. And that also avoids confusions in programs.

It is always a good idea to provide accessors because it is the way that OOP gurus would suggest. If you are quite "lazy" you can define a field public, i.e. accessible for outsiders. However, this kind of practice is often not desirable. By declaring a field public, it can be read and/or written by anyone. It will then create chaos, especially in large projects.

 

Public or Private

Declaring things as public means that it is accessible by outsiders. The other hand, declaring things private means that it is invisible by outsiders, thus making it unable to be accessed by anyone but the instance internal. What is the "public" and "private" here means? They serve as access keywords. They determine the grant policy of the accesses into that particular thing. Beside public and private, there is another access keyword: protected, which will be discussed later.  All things -- methods and properties -- must have access rights. In Object Oriented Pascal, all things inside the class are public by default. (Note: I think Borland Pascal manual has mistakenly stated that it is private by default). OK, where should I put those access keywords? Here is a rough idea:

type
  tMyClass = Object
                public
                   :
                   :  { All public methods and fields go here }
                   :
                private
                   :
                   :  { All private methods and fields go here }
                   :
              end;

How can we decide which methods or properties should be declared public and which ones should be private? Well, it depends on your need. However, there is a good rule of thumb: Usually, methods are declared public, unless the methods are internal to the instance (e.g.: helper methods) which will never be used outside the instance. Then, usually, properties are declared private. If some other class or instances want to access that particular variable, it has to access the accessor methods described above. The accessor methods are therefore have to be declared public. There are only two reasons that force you to make the properties public:

  1. It is a constant, so the values never changed anyway
  2. To improve speed if the property is often accessed. However, this is a bad habit. This job's usually been taken care of by the compiler better, so you won't need to do that.

OK, that's all for now folks. It will be continued later in part 2. I'll try to be as clear as possible.


Where to go?

Main tutorial page
Lesson 3 Index
Next Chapter 


Roby Joehanes © 2000