Copyright 1997 by Robert M. Keller, all rights reserved.
An object:
These two aspects are what defines object-oriented.
Example of objects with state:
Not every object is necessarily a visible or tangible one; objects can be highly abstract.
Ob . message(.... arguments ....)
The above two forms of modification are called side-effects. In functional programming, there are no side-effects.
Simula 67 (Norway, 1967)
Smalltalk (Utah, 1970)
C++ (New Jersey, 1986)
Java (Mountain View, 1995)
This is done in terms of methods
(in C++ the term member function is used).
Java is a strongly-typed language with dynamic polymorphism.
(called static information)
(called static methods)
Example: bouncing balls
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.
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 .... }
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
/** Make a deposit of a specified amount **/ public void deposit(int amount) { balance += amount; }
This method has no return value, hence the keyword void.
/** 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.
/** 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.
/** 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)
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
....
}
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.
/** * 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; }
/** * Issue statements for all accounts. **/ public void issue_statements() { for( int i = 0; i < num_accounts; i++ ) account[i].statement(); }
Actually, the objects contained in the lists can be mutable. However, the list structure itself is not.
The package is defined in /cs/cs60/java/Poly.
This package gives us much of the capability of lists as in rex (but no pattern matching, sorry; that is a syntactic issue).
Poly.List
denotes the List class within package Poly.
Other immutable classes, defined in package java.lang:
Wrappers are used to treat primitive data items as objects.
Table of Wrappers:
Wrapper type
Type wrapped
Extractor method
int
intValue()
long
float
double
boolean
char
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.
(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
etc.