Lecture 26 (Sherriff) - Creating Classes

Lecture Date: Friday, March 20

We continue with our exploration of classes today.

Let’s consider something really simple: a Rectangle.

First let’s draw a class diagram for Rectangle. To do this, we need to consider what makes up the state and behavior of our object. That is:

  • what makes this Rectangle different than any other and
  • what actions can we do with a Rectangle

So, what are the fields that make up a Rectangle? How about the x and y coordinates of the lower-left and upper-right corners?

We declare these at the top of the class like this:

Rectangle.java
1
2
3
4
5
6
7
8
9
public class Rectangle {
  
  private int x1;
  private int y1;
  private int x2;
  private int y2;
  
}
  

In general, you want your fields to be private. It allows you to “protect” them from accidental change. We’ll look at this a bit later.

How about methods? getPerimeter() and getArea() are nice.

But there are some other methods we need. Every class typically has a set of common methods that do effectively the same thing for each class.

The constructor is the method that “boots up” the class. It has no return type and might or might not have parameters. A constructor with no parameters is called a null constructor or default constructor. This is the absolute “default” version of a class. You should set the values of all the fields to default values here.

A constructor that takes a value for every field is called a full constructor. In this constructor, you simply set the fields equal to the appropriate passed-in parameter.

So, our constructors for Rectangle might look like this:

Rectangle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
public Rectangle() {
  this.x1 = 0;
  this.y1 = 0;
  this.x2 = 1;
  this.y2 = 1;
}

public Rectangle(int x1, int y1, int x2, int y2) {
  this.x1 = x1;
  this.y1 = y1;
  this.x2 = x2;
  this.y2 = y2;
}

The other types of methods are called getters and setters. These methods allow for the, well, getting and setting of field values. We use methods to do this to “protect” the fields.

Say for instance someone was using a Rectangle and accidentally tried to set the point “below” (0,0). We don’t want that (in our example at least). So in the setter, we can guard against it:

Rectangle.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void setLowerLeft(int x1, int y1) {
  if(x1 < 0) {
      this.x1 = 0;
  } else {
      this.x1 = x1;
  }
  
  if(y1 < 0) {
      this.y1 = 0;
  } else {
      this.y1 = y1;
  }
  
  return;
  
}

How about getting the area?

Rectangle.java
1
2
3
4
5
6
7
public int getArea() {
  int length = x2-x1;
  int height = y2-y1;
      
  return length * height;
}
  

Now what if we wanted to determine if two Rectangles were overlapping?

Rectangle.java
1
2
3
4
5
public boolean overlapsWith(Rectangle rect2) {
  boolean test = (this.x2 < rect2.x1) || (rect2.x2 < this.x1) || (this.y2 < rect2.y1) || (rect2.y2 < this.y1);
  return !test;
  
}