slanted W3C logo

Day 05 — Object-Oriented Programming

Today's class introduces some of the fundamental concepts of object-oriented programming. The idea of delegation and how it affects the client is emphasized.

Client-View Programming

client
a customer or patron; someone who receives a service

In 1020, the client is you, the programmer of the main method. You are called a client because you will need to shop for components that can provide you with services that can help you solve a programming problem.

We have already used one component named System.out; that component provided us with a service named println that let us send output to a console.

In Java, a component that provides a service is usually what we call an object; occassionally, the component is something else called a utility.

Objects

In the real world, an object is a physical thing (the person next to you, your shoe, your computer, etc.). Objects have state (properties) and behavior (actions they can perform).

"Lola" the Cat
State: name, color, weight, asleep, awake, crazy, ...
Behavior: sleep, sleep, sleep, eat, purr, ...

In Java, an object also has state and behavior. An object stores its state in fields (or attributes) and performs its behavior using methods. Often, the methods will cause the state of the object to change (by modifying its attributes). You can think of attributes as being variables that are owned by the object.

Classes

In the real world, there are many individual house cats; however, cats in general share enough common features that when someone says "my cat ..." everyone knows what you are talking about.

In Java, a class is a blueprint for constructing objects. A class defines what attributes an object will have (its state) and it defines what behavior an object can perform (its methods). Notice that a class groups related attributes and methods in one place.

A class defines a type; for example, if we had a Cat class, it would be possible to create variables of type Cat.

Using a class, the client can create many different instances of the class; for example, if we had a Cat class, we could create many objects, each one representing a different cat.

Delegation

to delegate
to entrust to another

As the client, you can choose to entrust information (data) or computation to an object or utility.

What are some advantages of delegating data storage?

What are some advantages of delegating computation?

Example: No Delegation

Suppose that you want to write a Java program that manipulates rectangles (for example, you want to be able to set the width and height of the rectangle, and compute its area). The non-delegating solution is for the client to manage the data (width and height) and computation (area) by herself:

public class RectangleArea
{
   public static void main(String[] args)
   {
      int width = 8;
      int height = 3;
      int area = width * height;

      System.out.println(area);
   }
}

Example: Procedural Delegation

An alternative solution is for the client to manage the data, but to ask a special kind of class called a utility to compute the area.

The only way that the utility can compute the area is for the client to supply the width and height. The client delegates the computation of the area to the utility by passing a message to the utility that describes the nature of the request (compute the area) and the data needed to perform the request (the width and height).

In Java, messages are passed by invoking a method. In Java, there are no standalone methods; a method always belong to class.

import type.lib.*;

public class RectangleArea1
{
   public static void main(String[] args)
   {
      int width = 8;
      int height = 3;
      int area = Rectangle1.computeArea(width, height);

      System.out.println(area);
   }
}

In the example above, the package type.lib defines a class named Rectangle1. The class Rectangle1 happens to define a method named computeArea. The method computeArea accepts two pieces of information, namely the width and the height. The method also returns a value, in this case the area of the rectangle, that has type int.

Notice the use of the . that separates the class name and the method name.

Example: Modular Delegation

Yet another solution is for the client to delegate the data and the computation to a utility that owns attributes corresponding to the width and height of a rectangle.

import type.lib.*;

public class RectangleArea2
{
   public static void main(String[] args)
   {
      Rectangle2.width = 8;
      Rectangle2.height = 3;
      int area = Rectangle2.getArea();

      System.out.println(area);
   }
}

In the example above, the package type.lib defines a class named Rectangle2. The class Rectangle2 defines both a width and a height attribute; the client can delegate the rectangle data to the utility in this case. Rectangle2 also defines a method called getArea. The method getArea accepts zero pieces of information because it does not need any information to perform the computation of the area; it already has access to the width and height attributes defined by the class. The method also returns a value, in this case the area of the rectangle, that has type int.

Notice the use of the . that separates the class name and the method name, as well as the class name and the attribute name.

When we use a utility, we can only represent one rectangle at a time. This can be inconvenient if our application needs to represent many different rectangles.

Example: Object-Oriented Delegation

The final solution is to delegate both data and computation to an object instead of a utility. This gives us the advantage of being able to create many rectangles with different dimensions.

import type.lib.*;

public class RectangleArea3
{
   public static void main(String[] args)
   {
      Rectangle3 r = new Rectangle3();
      r.width = 8;
      r.height = 3;
      int rArea = r.getArea();

      System.out.println(rArea);


      Rectangle3 s = new Rectangle3();
      s.width = 2;
      s.height = 10;
      sArea = s.getArea();

      System.out.println(sArea);
   }
}

In the above example, the class Rectangle3 is a class that defines a type named Rectangle3. We can create instances (variables) of type Rectangle3 using the new operator. The instance named r has its own width and height attributes that are distinct from those of the instance named s. A change to the width of r does not affect the the width of s; in other words, the client can change the state of r independently of the state of s.

Notice that the . is used as a separator between an instance name and an attribute, and an instance name and a method.