Encapsulation
1 Encapsulation

Encapsulation

CS 3500, Fall 2015

Back to Connect $N$

Our model’s interface

static enum Status { Playing, Stalemate, Won, }

Status getStatus();
boolean isGameOver();
int getNextPlayer();
int getWinner();

Integer getPlayerAt(int x, int y);
boolean isColumnFull(int which);

int move(int who, int where);

int getWidth(); int getHeight();
int getGoal(); int getPlayers();

What fields do we need?

int width;
int height;
int goal;
int players;
Status status;
int turn;

List<List<Integer>> columns;

How about some more flexibility‽

Why commit to players being ints?

int width;
int height;
int goal;
int players;

Status status;
int turn;

List<List<Integer>> columns;

More flexibility!

int width;
int height;
int goal;
int players;

Status status;
Object turn;

List<List<Object>> columns;

What if we want 3-D Connect $N$?

int width;
int height;
int goal;
int players;

Status status;
Object turn;

List<List<Object>> columns;

Or $k$-D Connect $N$?

int width;
int height;
int goal;
int players;

Status status;
Object turn;

List<List<Object>> columns;

That’s better

int width;
int height;
int goal;
int players;

Status status;
Object turn;

Object hypercolumns;

Width and height are only 2-D

int width;
int height;
int goal;
int players;

Status status;
Object turn;

Object hypercolumns;

Ah, this is more general

Map<String, Integer> dimensions;

int goal;
int players;

Status status;
Object turn;

Object hypercolumns;

But what about goal & players?

Map<String, Integer> dimensions;

int goal;
int players;

Status status;
Object turn;

Object hypercolumns;

Into the Map with them!

Map<String, Integer> configuration;




Status status;
Object turn;

Object hypercolumns;

In $k$-D, status might get interesting

Map<String, Integer> configuration;




Status status;
Object turn;

Object hypercolumns;

Better not limit it

Map<String, Object> properties;





Object turn;

Object hypercolumns;

Hmm, I dunno about turn

Map<String, Object> properties;





Object turn;

Object hypercolumns;

The Map means we decide later!

Map<String, Object> properties;







Object hypercolumns;

Go big or go home

Map<String, Object> properties;

Our model representation is now as flexible as can be

Do we like it?

ಠ_ಠ

What’s the trade-off here?

We gained flexibility

We lost meaning and intent

Let’s try the other direction

Does this representation allow too much freedom?

int width;
int height;
int goal;
int players;

Status status;
int turn;

List<List<Integer>> columns;

Bad freedoms

  • width or height or goal or players might change mid-game

  • status or columns might be null

  • width or height or goal or players might be zero or negative

  • the shape of the list-of-lists in columns might not match the dimensions in width and height

  • or it might contain Integers that don’t stand for actual players

  • and the client can look at or change whatever it pleases

Use final wherever you can

If it shouldn't change, let the compiler check for you that it doesn't

final int width;
final int height;
final int goal;
final int players;

Status status;
int turn;

List<List<Integer>> columns;

Use final wherever you can

If it shouldn't change, let the compiler check for you that it doesn't

final int width;
final int height;
final int goal;
final int players;

Status status;
int turn;

final List<List<Integer>> columns;

Use private whenever you can

As soon as a client depends on a field, you support that field forever

private final int width;
private final int height;
private final int goal;
private final int players;

private Status status;
private int turn;

private List<List<Integer>> columns;

Principle of least privilege

Every program and every privileged user of the system should operate using the least amount of privilege necessary to complete the job.

—Jerome Saltzer

Encapsulation

Any pair of integers looks like any other

Methods give meaning to the data

Hiding the fields preserves meaning and adds flexibility

Access levels

Access level modifiers

ModifierScope
privatesame class only
default...and everything else in the package
protected...and subclasses
public...and the rest of the world

Where can it be seen from?

Modifierclasspackagesubclassworld
private
default
protected
public

Who can see members of Base?

package left;                       package right;

public class Base { ... }           public class Derived
                                    extends Base { ... }

public class lefthelper { ... }     public class righthelper { ... }

ModifierBaseLeftHelperDerivedRightHelper
private
default
protected
public