Overview
What Sam hopes you took from the reading, or at least what Sam thinks you should know about the basics.
static
modifier.Question: What’s the difference between encapsulation and abstraction.
Clarify with example.
Suppose we’ve designed a list struct in C.
// listlib.c
struct list {
struct node* head;
struct node* tail;
int len;
}
// listlib.h
int length(struct list *lst);
// Client code
struct list *students;
...
if (length(students) < 5) {
cancelClass();
}
if (students->length < 5) { ... };
Let’s look at Java’s BigInteger class.
Suppose we want to design a class to represent Fractions (rationals).
Design choices we may have to make
public class Fraction {
// +------------------+----------------------------------------------
// | Design Decisions |
// +------------------+
/*
When do we detect "invalid" fractions?
* Constructors should fail when asked to create an invalid fraction. <-
* Let the client deal with issues. Pretend it's okay.
Do we store them in simplified state?
* If someone creates 2/4, do we store that as 1/2 or 2/4? If they
ask for the numerator, what do they get?
How do we deal with signs?
* Associated with the numerator. `new Fraction(1,-2)` => -1/2.
Mutable or immutable?
* Mutable objects can be changed. Vectors in Racket.
* Immutable objects cannot be changed. Lists in Racket.
* Mutable objects are (usually) more efficient; immutable objects are
(usually) easier to reason about.
What accuracy do we want? (may influence types for fields,
methods we write, etc.)
* Shorts, longs, ints, BigIntegers, ...
*/
// +--------+--------------------------------------------------------
// | Fields |
// +--------+
BigInteger numerator;
BigInteger denominator;
// +--------------+--------------------------------------------------
// | Constructors |
// +--------------+
public Fraction(int num, int denom) throws MathException {
this.numerator = new BigInteger(num);
this.denominator = new BigInteger(denom):
}
// Create the fraction whose numerator is num and denominator is 1.
public Fraction(int num) {
...
} // Fraction(int)
public Fraction(BigInteger num, BigInteger denom) throws MathException {
this.numerator = num;
this.denominator = denom;
}
// Create a fraction close to d
public Fraction(double d) {
...
} // Fraction(double)
// Parse a string to create a fraction
// e.g., new Fraction("123125612312321/12312380390234");
public Fraction(String description) throws ParseException,MathException {
}
// +---------+-------------------------------------------------------
// | Methods |
// +---------+
public Fraction add(int addend) { ... }
public Fraction add(Fraction other) { ... }
public BigInteger numerator() { ... }
public BigInteger denominator() { ... }
public BigInteger wholepart() { ... }
public Fraction fractional() { ... }
public Fraction reciprocal() throws MathException { ... }
public double toDouble();
} // class Fraction
Note: One of the main goals of this lab is to get you used to thinking
in Java object style. x.multiply(y)
rather than multiply(