17
$\begingroup$

While teaching OOP in a high school CS major (in java), it is important (and part of the curriculum in any case) to explain "what is the meaning of this public and private?" (A question voiced by many students).

The usual explanation is a technical one:

  • Something public is accessible from anywhere.
  • Something private is, well, private.
  • protected ??
  • default access (when no other access modifier is given).

As for protected, the students know about inheritance but the explanation of "it can be accessed by things down the inheritance tree" doesn't really get the idea through. Examples only show it so far and only works for a number of students.

So this got me thinking: How can access levels be explained in an intuitive way to high school students?

Note: I'm not only asking about protected, that is my main problem when explaining access levels.

Clarification

I am talking about access modifiers for objects and methods, not classes:

public class Example extends JFrame{ //the public in this line is not what I'm asking about.
    private int x; //this is the kind of private asked about
    protected void paintComponents(Graphics g){ //and this is also the kind being asked about.
$\endgroup$
3
  • $\begingroup$ You need examples of why you would use one access level over another to engage their intuition. $\endgroup$ Jun 30, 2017 at 2:34
  • $\begingroup$ @DominicCerisano yes. $\endgroup$
    – ItamarG3
    Jun 30, 2017 at 9:04
  • $\begingroup$ By that I mean actual programming examples, rather than merely mansplaining the difference between words which your students already know. $\endgroup$ Jul 4, 2017 at 23:45

11 Answers 11

32
$\begingroup$

Here's an analogy that I've used for several years, and that students seem to understand. It doesn't focus on the rules, but why we have public and private and protected.

"Most of you know that I live down at the beach. If you find yourself riding past my house, and it's hot outside, you might come to my front door, knock and ask if you could have a soda. I don't live in a gated community, so anyone can come to my front door and knock. My front door is public. However, you can't open the front door, walk right in to my kitchen, open the refrigerator door, and help yourself to a soda! My refrigerator door is not public.

My children and grandchildren, however, who live next door, think nothing of walking into the house and getting anything they like out of the refrigerator. In our house, the refrigerator is protected; my family can directly access it, but the general public cannot.

Not everything in our family is protected, though. My kids know that going upstairs, finding my Visa card, and charging a new book at Amazon, isn't permitted. My Visa card, and the contents of my wallet, are private. No one else can access them directly; they have to make a request."

$\endgroup$
5
  • 4
    $\begingroup$ I like this analogy very much. Short, to the point, and mimics the relationships well. Welcome to Computer Science Educators. I hope we hear more from you in the future! $\endgroup$
    – Ben I.
    Jun 29, 2017 at 22:00
  • $\begingroup$ I cannot express enough how useful this is. Thanks. (I will probably accept this soon) $\endgroup$
    – ItamarG3
    Jul 1, 2017 at 8:52
  • $\begingroup$ Ultimately it's all about security. All the examples above has to do with security, and the consequences of such can use the same framework. If your VISA card is made public, I don't think it takes a lot of imagination to know how bad that really is, so likewise, something like a "bank_balance" variable must definitely be extremely limited. You cannot just have any random objects modify it outside of specific withdraw() and deposit() methods. Likewise, a bank teller and an ATM are under the "authorized_entity" environment, and will probably have similar checks for withdraw() and deposit(). $\endgroup$
    – Nelson
    Jul 1, 2017 at 15:45
  • $\begingroup$ This answer explains (mansplains) what the difference is between words that students already know. It does not intuit why a particular OOP access level would be used over another. For that, actual programming examples would be required. Would that programming could be taught without programming, and instead by ESL. A popular but wishful fantasy. $\endgroup$ Jul 5, 2017 at 0:11
  • $\begingroup$ I like it. It shows how it Java (and all C++ based languages) model access for you, your children, and the public. It also shows how they think you hate your wife and friends. (Ok I forgot friends, you can give your friends access to your play-station, by using interfaces and friends). Eiffel solves this by allowing you simply to declare with classes can access which features of the class $\endgroup$ Jul 22, 2017 at 8:10
13
$\begingroup$

What my teachers used was the following example, which is pretty simple and most people understood.

Your father orders a pizza. The delivery guy arrives and expects payment. The wallet containing the money belongs to the object father

If the wallet is private, then you have to get your father to open it and pay.
If the wallet is protected, you can go and pay the pizza guy.
If the wallet is public, the pizza guy takes it and pays himself

$\endgroup$
2
  • 1
    $\begingroup$ Oh. Wow. This is incredible. Welcome to Computer Science Educators, I hope we'll be seeing more from you. $\endgroup$
    – ItamarG3
    Jun 30, 2017 at 13:20
  • $\begingroup$ One of the most important things I've found for teaching this concept is the idea that you could want to restrict access to data or functions. When we learn coding, "public" is kinda the default way most of us think. You have to realize there's value in constraining your options before you can understand why you want private. I think this series of examples using a wallet is an excellent argument for why sometimes you want constraints. $\endgroup$
    – Cort Ammon
    Jun 30, 2017 at 16:42
12
$\begingroup$

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:

  1. Is the area still correct? And
  2. 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:

  1. We make those Points and the area variables private.
  2. We create a getter for Area.
  3. We create setters for Rectangles Points.
  4. 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.

$\endgroup$
1
  • 1
    $\begingroup$ Excellent - there is nothing like a few code snippets to explain a coding concept. Thanks for not giving an ESL lesson on the difference between the words public, private, etc. $\endgroup$ Jul 5, 2017 at 0:12
2
$\begingroup$

I like to draw classes as boxes within each other to describe inheritance (ignoring multiple inheritance). So if Dog and Cat inherit from Animal, I'd have a box labeled Animal containing a Dog box and a Cat box. Inside each box, I'd have 2 sections: Public methods and private methods (and protected methods, which I won't talk about in this answer). Then, using this box drawing, I could indicate that the public methods can get out of the box and be made publicly available, whereas the private methods can't get out of their boxes.

Boxes with labels and arrows to where the methods can be called from

This same idea could also be expressed as a tree structure:

Animal
   change_name (public)
   Dog
      bark (public)
      validate_name (private)
   Cat
      meow (public)
      validate_name (private)

In that case, public methods can change levels of the tree in either direction, and private methods cannot exit their level (or move to a different class in their level. This part is clearer with boxes).

$\endgroup$
0
2
$\begingroup$

The fact that OO languages support public and private methods and data members is a crucial, important design choices.

And to get a full, deep understanding of how OO programming works, it is crucial to understand both how they work, and when you'd want to use them, which is another way of explaining why they are in the language.

Many of the analogies in the answers so far can help students learn "how they work", but I wonder whether they break down at some point in explaining "when" to make something public or private, and therefore the "why".

Part of the problem is that we often teach with classes such as this:

public class Student {
  // data members
  private int idNum;
  private String name;

  // getters
  public int getIdNum() { return idNum; }
  public String getName() { return name; }

  // setters
  public void setIdNum(int idNum) { this.idNum = idNum; }
  public void setName(String name) { this.name = name; }
}

The problem here is that in this class, given that the getters and setters simply provide direct access to reading and writing a primitive value, it is very difficult to argue that they add any value. To come up with a justification for why name and idNum are private, we have to use arguments that are not very convincing.

It becomes easier to see if you have an abstract data type such as a Dictionary with keys and values that allows insertion and deletion, where it can be implemented (internally) in many different ways: linked lists, hash tables, balanced lookup trees.

You can show that by keeping the details of the internal state private, it is possible to swap out different implementations without needing to change the code that uses the data structure.

But, of course, this is a much more sophisticated example. It requires more understanding of "where we are headed down the road" then students are typically equipped to understand, or teachers are in a position to explain, if/when students encounter Java as a first programming language.

It is the reason that, from where I sit, Java is an excellent choice of second, or third language, for students that have already done enough programming to appreciate the need for data abstraction and information hiding, because they've tried to write fairly complex programs without those tools.

It is, however, a poor choice of language to teach first, because it requires students to "accept on faith" many principles of OOP that they have no motivation, reason, or background to understand yet.

I am fully aware that this is an iconoclastic point of view, and "fighting words" for many of the OOP true believers. I'm fully prepared for the backlash. :-)

$\endgroup$
1
  • 1
    $\begingroup$ Encapsulation is probably the most universal feature of OOPS, and the most necessary, so it is a great place to start. $\endgroup$
    – user737
    Jun 30, 2017 at 0:06
2
$\begingroup$

Unfortunately this question depends on the language. I'll give a general discussion but focus on Java.

public is, as you say visible from any code in the program (and in the original java concept that meant visible across the globe com.sun.java.Foo.x can be found on your computer - or could be, anyway, in theory).

private can mean (a) visible from anywhere in this class (java) or (b) visible only from this specific object. Object level private is an interesting idea, not often implemented. Usually "private" means class level.

In java, not giving any indication (blank) means visible anywhere in this package and this only means something if all your code is in one package or another. In scala (blank) means public. BTW, it should be in a package.

protected means visible throughout this package AND ALSO visible in subclasses of this class defined outside this package. This is dangerous to use, since it is broader than (blank). It is useful for library code, however.

I know I didn't really give an intuitive answer. For beginners the visibilities should really be public or private. Protected is for libraries primarily and they aren't doing that, I think, and blank is a way to build buggy code since the visibility across their various classes is likely to get them in trouble. So,

Public - like the library
Protected - like the book shelf in your team's workspace
Private - like my bookshelf at home.

Note also that the purpose of visibility, the intention of language designers, is to restrict who (which programmers) can reference code, not which code can reference code. It is intended to facilitate teams working on different parts of a large application and permitting them to work in a namespace (say a class, or a package) in which the work of other programmers doesn't impede progress. Negotiation need to occur only at the boundaries, not over every name everywhere in a (say) 30 million line program. Generally a single programmer (or pair) is, at any given time, responsible for a class. A small team, perhaps, for a package.

$\endgroup$
11
  • $\begingroup$ private is *not often implemented? Urrrm, I don't think so... $\endgroup$
    – ItamarG3
    Jun 29, 2017 at 18:19
  • 2
    $\begingroup$ Object level private is not often built in to languages, class level private is common; a distinction. It is a language function, not a program choice. Clarified in the answer, I hope. $\endgroup$
    – Buffy
    Jun 29, 2017 at 18:21
  • $\begingroup$ They are not complete novices. .. but the bookshelf analogy is very nice. $\endgroup$
    – ItamarG3
    Jun 29, 2017 at 18:24
  • $\begingroup$ Yeah, forehead-slap moment when I first thought through the distinction of class-private vs object-private. Obvious, once I saw it. Yes, not usually talked about. $\endgroup$
    – user737
    Jun 29, 2017 at 23:56
  • $\begingroup$ I emphasized class v object private since students often get it wrong. I once built a language that had object-private (for my compiler course) and learned that it has issues/problems/grief. But note that such a feature protects code from other code, rather than code from other programmers. One object can't, in such a system, step on the state of another, even in the same class. But one programmer programmed both objects by building their class so is able to prevent inconsistent state. Theoretically. Though bugs happen. $\endgroup$
    – Buffy
    Jun 30, 2017 at 0:39
1
$\begingroup$

I have a distinct memory of my college CS teacher saying "only your friends can touch your privates". The context was C++, and yes there was an accompanying eyebrow waggle.

The meaning was pretty clear & I still remember it after >15 years.

Of course, you may have to tone it down some for high school, but the analogy to one's privates could be useful.

$\endgroup$
1
  • $\begingroup$ Depending on who says it, your tenure may vary. "Is this the time for a colorful metaphor?" (Spock) $\endgroup$
    – user737
    Jun 30, 2017 at 0:09
1
$\begingroup$

Unless this is an honors programming class, access modifiers may be difficult to understand. I usually start with public vs. private and provide a simple case. For example, it is usually a bad idea to make an instance variable public:

public class Person {
  public int age;   
  public static void main(String[] args) {      
    Person p = new Person();        
    p.age = -99; //bad, but legal       
  }
}

Instead, make age private and provide public accessor methods:

public class Person {
  private int age;
  public static void main(String[] args) {
    Person p = new Person();
    p.setAge(22); //nice.       
  }

  public void setAge(int age) {
    if (age < 0) {
        System.err.println("error - bad age: " + age);
        age = 0;
    } else
        this.age = age;
  }

  public int getAge() {
    return age;
  } 
}
$\endgroup$
1
$\begingroup$

I use phone numbers.

You know your cell phone number, and I don't. That makes it a private instance variable. I have no way to get it without you telling it to me.

If it was a public instance variable, instead of you knowing it and me not, it would be tattooed on your forehead. Then, when the creepy guy who wants to ask you out sees you in the hall he can look at your forehead, get your number, and put it in his phone. Congrats, you have your very own stalker.

But you do want to give out your phone number to some people, just as long as you can control who gets it. For that you need to keep the instance variable private, but make a public getter / accessor method like getPhoneNumber(). Now you can do whatever you want to decide if you want to share your phone number with the guy in the hall. Is he creepy? Does he have nice friends? Is he missing teeth? Does he drive a nice car? It's up to you to decide.

And then we backtrack a bit. Tattooed on your forehead is a little over simplified. If it was truly public, anyone could change it. It's more like it was written with washable Crayola marker. Works as a hook for why we need both accessors and modifiers.

I teach mainly AP-A in high school, so those are the only two modifiers I really worry about. We brush on protected when we get a little deeper into inheritance, but by that point they've got public / private down pretty well so it's a short hop.

$\endgroup$
8
  • $\begingroup$ That's a good analogy for how private works in Ruby, for example, but in Java, privates are visible to other objects. $\endgroup$ Jun 30, 2017 at 7:17
  • $\begingroup$ @JörgWMittag urm. not they're not. maybe with Getters and Setters, but not directly. $\endgroup$
    – ItamarG3
    Jun 30, 2017 at 11:21
  • $\begingroup$ That's backwards of how I learned and understand it. Private in Java is not accessible for outside classes. $\endgroup$
    – Ryan Nutt
    Jun 30, 2017 at 11:22
  • $\begingroup$ @ItamarG3: Here's a demo: ideone.com/nQtdh6#sthash.5nNWwgZY.dpuf $\endgroup$ Jun 30, 2017 at 11:54
  • $\begingroup$ @RyanNutt: Here's a demo: ideone.com/nQtdh6#sthash.5nNWwgZY.dpuf $\endgroup$ Jun 30, 2017 at 11:54
1
$\begingroup$

This year, I used the example of student grades that seemed to work pretty well (C++):

  • The Student class has a private _grade.
  • Every student can see every other student's grade.
  • However, an InsuranceCompany cannot see a student's grade.
  • For convenience, I want that a Teacher can see and change a Student's grade. For this reason, the Student defines the Teacher as friend.
    • Of course, the Teacher does not define the Student as friend, so the student cannot see the teacher's grade.
  • Regarding protected, one can use students of specific programs or levels.

The fact that "every student can see each other student's grade" seemed to concern my students and stick quite well, triggering interesting questions ("but how I can do that per object?").

$\endgroup$
-3
$\begingroup$

I think a good way of looking at it is like legislation in the United states. Public would be national law, it impacts everyone in the country. Private is like state or city level law, much smaller scope. Now, all this legislation fits into the protected category because of ex post facto (after the fact in Latin). If you do something legal, and later it becomes illegal, you cannot get charged for the previous action. One can only be charged if the crime is committed after the legislation is passed.

An example:

  • (PUBLIC, protected) National level: Pot is completely illegal.

  • (PRIVATE, protected) Colorado: Pot is legal for medicinal and recreative use.

$\endgroup$
8
  • $\begingroup$ I'm not sure I see how the last to sentences are related... Could you expand on that? $\endgroup$
    – ItamarG3
    Jun 29, 2017 at 17:55
  • $\begingroup$ Does that help? $\endgroup$ Jun 29, 2017 at 17:58
  • $\begingroup$ But how is it related to oop? $\endgroup$
    – ItamarG3
    Jun 29, 2017 at 17:59
  • $\begingroup$ This fits for JS OOP so I don't know if the idea gets across to other languages or not $\endgroup$ Jun 29, 2017 at 18:02
  • 1
    $\begingroup$ I'm not sure I understand your example, but find it confusing. visibility is about, well, visibility. Laws are about applicability. A private method can have a global effect on a computation, though it can't be referenced globally. $\endgroup$
    – Buffy
    Jun 29, 2017 at 18:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.