Ooh, this is one of my favorite lessons!
I don't introduce package private and protected in the same lesson as private and public, because there are 3 principles that I want them to absorb that ultimately motivate the entire system. My lesson introduces a few more ideas than just permissions (it's really how I get started with Ojects), but the key ideas of encapsulation also lie therein. The lesson works roughly like this:
Students always default to wanting everything to be public
, so I provide a motivating example for why this is a bad idea. The entire set of steps is rather long, but I will create the setup and give a broad outline of how I proceed from there.
First, up on the projector, I create a point object:
public class Point{
public double x;
public double y;
}
I next create a Geometry
class into which I put my public static void main(String[] args)
. I create a point, and show them how to use direct access of public variables: myPoint.x
and myPoint.y
. At this point, we have basically created a struct. When it comes time to print out a few of these points, I create a toString()
Then I create a rectangle class:
public class Rectangle{
public Point p1;
public Point p2;
public double area;
public Rectangle(
}
.... right here, I stop, and ask the class how we should create our two points. This is when I get to the Motivating Principle #1: it is the responsibility of an object to care for and ensure its own variables. Which leads to the question: who should directly set the actual x
and y
values in each of the two points, the Point
object, or the Rectangle
?
Given principle #1 (which I have not yet justified), we opt for the Point
object. So, before we continue with Rectangle
, we go back and create a constructor for Point
.
Before we resume this narrative, the astute reader will notice that the seeds of our destruction are already present in those public
variables!
My next stop is to finish the Rectangle
constructor:
public Rectangle(double x1, double y1, double x2, double y2){
p1 = new Point(x1,y1);
p2 = new Point(x2,y2);
area = Math.abs(x1-x2) * Math.abs(y1-y2);
}
We are almost ready to blow everything up. I go back to Geometry
, create a Rectangle
, and then... modify its area!
Rectangle r = new Rectangle(0.0,0.0, 1.0,1.0);
System.out.println(r.area);
r.area = Math.PI;
System.out.println(r.area);
At this point, we get to some obvious questions:
- Is the area still correct? And
- who is responsible to prevent this sort of malfeasance, anyway?
Looking at principle #1, we discover that, though the fault probably likes with Geometry
, the real responsibility here lies with Rectangle
. This immediately motivates a series of cascading changes:
- We make those
Point
s and the area
variables private.
- We create a getter for Area.
- We create setters for
Rectangle
s Point
s.
- We make
x
and y
private in Point
, and make getters (but no setters - we just use the constructor here)
In the follow-up discussion, we get to Motivating Principle #2: always provide the least permissions that you can get away with. This is what prevents trouble, and helps Objects to guarantee their part of Principle 1.
And finally, I bring them to my Warning Principle #3: getters and setters are how we grant access to a shielded variable, but if you've created an unmodified (straight/unfiltered) getter and an unmodified setter on the same variable, you are doing it wrong, and you have just made a public variable.
What follows is a series of short Object-design tasks in which I tell them to sketch out, for a series of theoretical private instance variables, appropriate getters and setters. After each one, we put a student's answer up and I let the kids discuss/critique/defend what is up on the projector. This gives us a chance to practice our three principles together, and really drives the point home.
I give this lesson high marks, historically, for squelching both public
instance variables, and de-facto public
created by unfiltered getters and setters on the same variable. Instead, I have found that students generate much more thoughtful object designs.