Object-Oriented Programming

Robert M. Keller

Copyright 1997 by Robert M. Keller, all rights reserved.

 


What is it?

One of the major programming paradigms, actually a sub-paradigm of imperative programming:


Why is it used?

 

Object-oriented programming is thus complementary to functional programming.

The two can be used together quite effectively.


In object-oriented programming, the state of the program is distributed among one or more objects.

An object:

These two aspects are what defines object-oriented.

Example of objects with state:

A drawing program.

Not every object is necessarily a visible or tangible one; objects can be highly abstract.


An object forms a kind of contract with its environment:


The protocol is often expressed as "sending a message" to the object:

Ob . message(.... arguments ....)


Side-Effects

 

The above two forms of modification are called side-effects. In functional programming, there are no side-effects.

 


Typically, object-oriented programming languages also provide for:

 


Java is an object-oriented language.

Java's pedigree:

Simula 67 (Norway, 1967)

Smalltalk (Utah, 1970)

C++ (New Jersey, 1986)

Java (Mountain View, 1995)


The Class of an object typically defines the following:

 

Java is a strongly-typed language with dynamic polymorphism.


In addition, a class may define:


In Java, classes also have uses such as:


Program Organization in Java:

Just about everything is inside of some class, except for:

Even code which is not particularly object-oriented is inside of some class in the form of static methods (there are no things called functions in Java).

Likewise, there are no structs in Java. These too are subsumed by classes.


Every object is an instance of some class


Class Example - A Bank Account

class BankAccount
{
private int balance;       // this account's balance
 
private int number;        // account number
 
String owner;              // name of account owner
 
String owner_ss_no;        // owner's social security number
 
static int last_acct = 0;  // account number counter
 
.... methods ....
}
 


A Constructor defines how an object is created

 
public BankAccount(String owner,         // Call this the head
                   String owner_ss_no, 
                   int initial_balance)
  {
  this.owner = owner;                    // Call this the body
  this.owner_ss_no = owner_ss_no;
  balance = initial_balance;
  number = ++last_acct;
  }
 

The keyword

this 

refers to this object (the one being constructed).

 

Variables local to constructors and methods shadow or over-ride instance variables with the same name.

 

To get to the instance variables, we can qualify them with this. Above we do this for variables:

owner
owner_ss_no

It is not necessary for variable

balance

which is not shadowed (there is no balance in the head).

Variable

number

is an instance variable which is set from a static variable

last_acct


Example of a method:

 

/**
     Make a deposit of a specified amount
 **/
 
public void deposit(int amount)
  {
  balance += amount;            
  }

 

This method has no return value, hence the keyword void.


Another method:

 

/**
     Try to make a withdrawal 
         of a specified amount.
     Return true if this was possible, 
            false otherwise. 
 **/
 
public boolean withdraw(int amount)
  {
  if( amount > balance )
    return false;             // unsuccessful
 
  balance -= amount;          // successful
  return true;
  }
 

 

This method has a true/false return value, hence the keyword boolean.


Yet another method:

 

/**
     Print a statement for the account.
 **/
 
public void statement()
  {
  System.out.println("Balance in account number " 
                     + number + " is " + balance);
  }

When the + operator is used with Strings, concatenation is implied. Numbers and other data are converted to Strings, then concatenated.

System.out identifies the standard output stream, which is normally directed to the terminal, but which may be redirected to a file on the command line.


Use of constructors and methods:

 
/**
     BankAccount test program.
 **/
 
public static void main(String args[])
  {
  // declare accounts
  BankAccount a, b, c;
 
  // create accounts:   Name   ss_no  initial balance
  a = new BankAccount("Alice", "991",  15000);
  b = new BankAccount("Wei",   "995", 200000);
  c = new BankAccount("Helga", "998", 100000);
 
  // use accounts
  b.deposit(5000);
  c.deposit(50000);
 
  if( !a.withdraw(5000) )
    {
    System.out.println("Insufficient funds in " + a.number);
    }
 
  if( !a.withdraw(11000) )
    {
    System.out.println("Insufficient funds in " + a.number);
    }
 
  // print statements
  a.statement();
  b.statement();
  c.statement();
  }
}

 

main is a name which is special to java; when the class is executed from the command line, it is this static method which gets called.

main must have an array of String arguments as shown.

main has void return type.

main does not depend on a specific object, and therefore is static (when main is called, no objects have been created yet)


Objects can be embedded within other objects.

A Bank might well contain an array of BankAccounts.

class Bank

{
int max_accounts;       // maximum number of accounts
 
BankAccount account[];  // declare array of bank accounts
 
int num_accounts;       // current number of accounts
 

....

}

 


ABank is a class:

there will be a constructor for creating banks,

in which the maximum number of accounts might be specified:

 
/**  
 *   Constructor, open a bank with a maximum number of accounts
 **/
 
public Bank(int max_accounts)
  {
  this.max_accounts = max_accounts;
  num_accounts = 0;
  account = new BankAccount[max_accounts]; // allocate array
  }                                        // (not accounts themselves)
 

At this point, the accounts themselves don't exist yet; only the array which will ultimately contain them does.

 

In general, there is no need to pre-specify a maximum number of accounts; the number can grow dynamically, e.g. by re-allocating the array. This is just an example for sake of discussion.


A method for the Bank class:

 
/**  
 *   Open a new account at this bank
 **/
 
public boolean open(String name, String ss_no, int balance)
  {
  if( num_accounts == max_accounts )
    return false;                   // reached maximum number
 
  account[num_accounts++] = 
 
    new BankAccount(name, ss_no, balance);
 
  return true;
  }
 

Another method for the Bank class:

 
/**  
 *   Issue statements for all accounts.
 **/
 
public void issue_statements()
  {
  for( int i = 0; i < num_accounts; i++ )
    account[i].statement();
  }
 
 

When an object cannot modify its own state, it is called immutable.

 


Classes within a package a referred to by using dot qualification, e.g.

Poly.List

denotes the List class within package Poly.

 

Other immutable classes, defined in package java.lang:

The extractor methods get primitive data values from a wrapper type. In addition, other extractors are available where they make sense. For example, longValue(), floatValue(), and doubleValue() are also a methods for type Integer.

 


S expressions represent lists and atoms

(This is (a list) with 5 elements)

ThisIsAnSexpressionToo

123

45.67e-89

A Poly.Tokenizer reads a whole S expression at once:

A list can then be decomposed using methods such as


Examples in /cs/cs60/java


Applets