This page contains an archived post to the Java Answers Forum made prior to February 25, 2002.
If you wish to participate in discussions, please visit the new
Artima Forums.
Message:
Access Modifier Musings...
Posted by Isa Leshko on July 04, 2000 at 12:53 PM
Hi Erik, I agree that that working with access modifiers can be a bit tricky, particularly to those new to Java. Let me first briefly summarize the differences between public, private, "friendly" (package) and protected access modifiers. Think of these modifiers as a means of controling access of particular features of a given class. Class features include: o the class itself o its class variables o its methods and constructors Note that only class-level variables can and should be controlled by access modifiers. This idea makes sense, actually, when you remember that variables local to a method can only be used within that method. OK, so now the summary of the modifers. Liberally snipped from "The Complete Java 2 Certification Study Guide" by Simon Roberts, Philip Heller, and Michael Ernest. These modifers below are ordered from least to most restrictive. o public: A public feature may be access by any class at all. For example, applets are declared public so they may be instantiated by browsers. o protected: This name is somewhat confusing, since it implies a fairly restrictive level of access. The reality is that protective features are more accessible than so-called friendly or private features. A protected feature may only be accessed by a subclass of the class that owns the feature, or by a member of the same package as the class that owns the feature. For more information on packages, see the "Creating and Using Packages" from the Sun Java Tutorial: http://java.sun.com/docs/books/tutorial/java/interpack/packages.html o friendly (aka package) Friendly or package-level access is the default level when no other modifier is specified. A friendly feature may be access by any class residing in the same package as the class that owns the feature. Classes outside the package may not access a friendly feature. Otherwise, that would be the same level of access as public! Here's one thing that will make your head hurt. Assume that we have a Shape class that resides in package com.cadac.abstract and we have a Rectangle class that extends Shape, but resides in a different package, say, com.cadac.concrete. Even though Rectangle is a subclass of Shape, it cannot access Shape's friendly members. That is because Shape resides in a separate package. You would need to make Shape's members protected (or public) if you wanted to provide Rectangle access to them. One additional note about the friendly access modifier. Many new Java programmers have the tendency to not specify any modifier (thereby using the friendly) modifier. They also have a tendency to not venture into using packages, and instead save all of their code in one directory. Keep in mind that the Java runtime environment considers any classes sharing a directory to reside in the same package. So, if you develop all of your programs in one directory, and don't specify any access modifers for your class members, you end up with quite an insecure mess. All of your classes, regardless of their functionality can access members of all the other classes in that directory. It's therefore a good idea to get familiar with working with packages and access modifiers as soon as possible. :-) o private: This modifer is the most restrictive. A private feature may only be accessed by the class that owns the feature. The principle of encapsulation dictates that data members and other implementation details are hidden from users of a class. However, the public interface of a class (i.e., members accessible to other classes) could include accessor and/or mutator methods. These public methods allow users of the class to view or manipulate the value of a private data member: // accessor or "getter" method public void getSomeValue() { return someValue; } // mutator or "setter" method public int setSomeValue(int someValue) { // error checking can go here! this.someValue = someValue; } Yes, having to write all of these extra methods can be tedious. But you gain significant benefits: o You can modify the internal implementation of your class without affecting other classes that use this class; o You can add error checking into mutator methods; o It's also easier to detect and resolve bugs if you consistently manipulate a data member using a mutator method. Now, to answer your specific question: > It is this idea that a class derived from >another class ('extends') does not inherit private members >from the base class. Actually, it *does* inherit these members. A subclass inherits all of the functionality of its parent class. Nonetheless, it cannot access or manipuate private members of its parent even though it technically "owns" them too. Other fine print involving the private modifer: o Top-level classes cannot be declared private. o Any instance of a given class can access private members of another instance of that class. The following code snippet from "The Complete Java 2 Certification Study Guide" illustrates this point well: class Complex { private double real, imaginary; public Complex(double r, double i) { real = r; imaginary = i; } public Complex add(Complex c) { // note that it's perfectly legal for // this method to access real and imaginary // belonging to another instance of Complex // even though these data members are private double newRealValue = real + c.real; double newImaginaryValue = imaginary + c.imaginary; return new Complex(newRealValue, newImaginaryValue); } } class Client { void useThem() { Complex c1 = new Complex(1, 2); Complex c2 = new Complex(3, 4); Complex c3 = c1.add(c2); // the following line, though, is illegal // because real is private and Client is // a distinct class from Complex. double d = c3.real; } } One additional important point on this topic involves overriding methods. A subclass is able to define a new behavior for a method that it inherits from its super/parent class. For example, the Shape class may have an abstract method named draw(). Rectangle will inherit this method when it extends Shape, and it will define its own behavior for drawing itself, thereby overriding the Shape version of draw.
When you override a method, you can change its access level providing that you do not make it more private. For example, if a parent class has a public method named foo, its child class can not make foo private. Doing so will generate a compiler error that says, "Methods cannot be overriden to be more private." The following figure from "The Complete Java 2 Certification Study Guide" summarizes the legal path for overriding a method with a different access type: private -> friendly -> protected -> public For more information on Overriding methods, see the following chapter from the Sun Java Tutorial: http://java.sun.com/docs/books/tutorial/java/javaOO/override.html For more information on the above Access Modifiers, see the "Controlling Access to Members of a Class" chapter of the Sun Java Tutorial: http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html Another great resource is the "Encapsulation" chapter from Lynn Andrea Stein's Intro to Interactive Programming: http://www-cs101.ai.mit.edu/ipij/procedures.html This is probably more information than you needed or wanted, but I had fun writing this message. :-) Seriously, hope this info helps. --Isa
Replies:
|