05b: OOP Principles

ICS211, Fall 2012
Dr. Zach

(switch view)

Status check

Quick History of Software (1/2)

Quick History of Software (2/2)

Lessons from Computing History

Trends (what we've learned works well):

Software Engineering Principles --> OOP

Encapsulation

Example: Square, No Encapsulation

public class Square {
  public int side;
  public int area;
  public int perimeter;
  
  public Square(int side) {
    this.side = side;
    this.area = side * side;
    this.perimeter = 4 * side;
  }
}

Example: Square, With Encapsulation

public class Square {
  private int side;
  private int area;
  private int perimeter;
  
  public Square(int side) {
    this.setSide(side);  //call method to do necessary work
  }
  
  public int getSide() {
    return this.side;
  }
  
  public void setSide(int side) {
    this.side = (side < 0) ? 0 : side;  //side must be 0+
    //recalculate all details
    this.area = this.side * this.side;
    this.perimeter = 4 * this.side;  
  }

  public int getArea() {
    return this.area;
  }

  public int getPerimeter() {
    return this.perimeter;
  }
}

Encapsulation Advantages

Example: Square, with implementation changed

public class Square {
  private int side;
  
  public Square(int side) {
    this.setSide(side);  //call method to do necessary work
  }
  
  public int getSide() {
    return this.side;
  }
  
  public void setSide(int side) {
    this.side = (side < 0) ? 0 : side;  //side must be 0+
  }

  public int getArea() {
    return this.side * this.side;
  }

  public int getPerimeter() {
    return 4 * this.side;
  }
}

If implementation is private, can change it without breaking existing code that uses public interface

Encapsulation Disadvantages

Advantages really pay off in large projects; not so much in small ones.

Sidenote: Various meanings of "user"

Abstraction

Reuse

Abstract Data Types (ADTs)

ADT: Stack

What is a data structure?

Abstract Data Type (ADT)

(In casual discussion, "data structure" and "ADT" often overlap. But sort of like difference between "method" and "algorithm".)

ADT: Stack

ADT: Stack, renamed

ADT: Stack, as Java code

To implement, need to know type of contents; use String for now...

public class Stack {

  public Stack() { ... }

  public void push(String item) {...}

  public String pop() {...}

  public String peek() {...}

  public int size() {...}
}

How do we use this?

  Stack s = new Stack();
  System.out.println(s.size());  //0
  s.push("Alice");
  s.push("Bob");
  s.push("Carol");
  System.out.println(s.size());  //3
  System.out.println(s.peek());  //Carol
  System.out.println(s.pop());   //Carol
  s.pop();
  System.out.println(s.peek());  //Alice
  System.out.println(s.size());  //1

What would this print?

(Again, as an ADT, should just need to know the defined behavior of the stack, not how it works inside.)

ADT: Stack implementation


ADT: Stack code

public class Stack {

  private static final int SIZE = 5;

  private String[] items;  //holds contents
  private int top;         //index of current top element

  public Stack() {
    this.items = new String[SIZE];
    this.top = -1;
  }

  public void push(String item) {
    this.top++;
    this.items[this.top] = item;  //XXX: What if array is full?
  }

  public String peek() {
    return this.items[this.top];  //XXX: What if stack is empty and top == -1?
  }
  
  public String pop() {
    String item = this.items[this.top];  //XXX: What if stack is empty?
    this.top--;
    return item;
  }
  
  public int size() {
    return this.top + 1;
  }
}

//XXX: Problems

Java: Throwing Exceptions

Java: Throwing Exceptions

public void foo() {
  IllegalStateException err = new IllegalStateException();
  throw err;
}
public void foo() {
  throw new IllegalStateException();
}

Java: Throwing Exceptions

/**
 * Computes factorial of n.  
 * n must be positive or else throws IllegalArgumentException.
 */
public int factorial(int n) throws IllegalArgumentException {
  if (n < 0) {
    throw new IllegalArgumentException("Cannot compute factorial of a negative number.");
  }
  int fact = //...compute factorial here...
  return fact;  
}

ADT: Stack code, revised

public class Stack {

  private static final int INITIAL_SIZE = 5;

  private String[] items;  //holds contents
  private int top;         //index of current top element

  public Stack() {
    this.items = new String[INITIAL_SIZE];
    this.top = -1;
  }

  public void push(String item) {
    this.top++;
    if (this.top == items.length) {
      //array is full, so replace with a copy that is double current size
      this.items = java.util.Arrays.copyOf(this.items, this.items.length * 2);
    }
    this.items[this.top] = item;
  }

  public String peek() throws IllegalStateException {
    if (this.top < 0) {
      throw new IllegalStateException("Can't peek() into empty stack.");
    }
    return this.items[this.top]; 
  }
  
  public String pop() throws IllegalStateException {
    if (this.top < 0) {
      throw new IllegalStateException("Can't pop() from empty stack.");
    }
    String item = this.items[this.top]; 
    this.items[this.top] = null;  //optional, but allows garbage collection
    this.top--;
    return item;
  }
  
  public int size() {
    return this.top + 1;
  }
}

ADT: Stack, conclusion

Next time...