续《JAVA编程思想》学习备忘(第209页:Access Control)-2
Interface and implementation
Access control is often referred to as implementation hiding.Wrapping data and methods within classes in combination with implementation hiding is often called encapsulation.the result is a data type with characteristics and behaviors.
Access control puts boundaries within a data type for two important reasons.The first is to establish what the client programmers can and can't use.You can build your internal mechanisms into the structure without worrying that interface that they should be using.
This feeds directly into the second reason,which is to separate the interface from the implementation.If the structure is used in a set of programs,but client programmers can't do anything but send messages to the public interface,then you are free to change anything that's not public(e.g.,package access,protected,or private)without breaking client code.
For clarity,you might prefer a style of creating classes that puts the public members at the beginning,followed by the protected,package-access,and private members.The advantage is that the user of the class can then read down from the top and see first what's important to them(the public members,because they can be accessed outside the file),and stop reading when they encounter the non-public members,which are part of the internal implementation:
将public成员置于代码开始处的示例:
//:access/OrganizedByAccess.java
public class OrganizedByAccess{
public void pub1(){}
public void pub2(){}
public void pub3(){}
private void priv1(){}
private void priv2(){}
private void priv3(){}
private int i;
//...
}
This will make it only partially easier to read,because the interface and implementation are still mixed together.That is,you still see the source code-the implementation-because it's right there in the class.In addition,the comment documentation supported by Javadoc lessens the importance of code readability by the client programmer.Displaying the interface to the consumer of a class is really the job of the class browser,a tool whose job is to look at all the avalible classes and show you what you can do with them(i.e,what members are available)in a useful fashion.In Java,viewing the JDK documentation with a Web browser gives you the same effect as a class browser.
Class access
In Java,the access specifiers can also be used to determine which classes within a library will be available to the users of that library.If you want a class to be available to a client programmer,you use the public keyword on the entire class definition.This controls whether the client programmer can even create an object of the class.
To control the access of a class,the specifier must appear before the keyword class.Thus you can say:
public class Widget{
Now if the name of your library is access,any client programmer can access Widget by saying
import access.Widget;
or
import access.*;
However,there's an extra set of constraints:
1.There can be only one public class per compilation unit(file).
2.The name of the public class must exactly match the name of the file containing the compilation unit,including capitalization.
3.it is possible,though not typical,to have a compilation unit with no public class at all.
Note that a class cannot be private(that would make it inaccessible to anyone but the class)or protected.So you have only two choices for class access:package access or public.If you don't want anyone else to have access to that class,you can make all the constructors private,thereby preventing anyone but you,inside a static member of the class,from creating an object of that class.Here's an example:
//:access/Lunch.java
//Demonstrates class access specifiers.Make a class
//effectively private with private constructors:
class Soup1{
private Soup1(){}
//(1)Allow creation via static method:
public static Soup1 makeSoup(){
return new Soup1();
}
}
class Soup2{
private Soup2(){}
//(2)Create a static object and return a reference
//upon request.(The "Singleton" pattern):
private static Soup2 ps1 = new Soup2();
public static Soup2 access(){
return ps1;
}
public void f(){}
}
//Only one public class allowed per file:
public class Lunch{
void testPrivate(){
//Can't do this! Private constructor:
//! Soup1 soup = new Soup1();
}
void testStatic(){
Soup1 soup = Soup1.makeSoup();
}
void testSingleton(){
Soup2.access().f();
}
}
Up to now,most of the methods have been returning either void or a primitive type,so the definition:
public static Soup1 makeSoup(){
return new Soup1();
}
might look a little confusing at first.The word Soup1 before the method name(makeSoup)tells what the method returns.So far in this book,this has usually been void,which means it returns nothing.But you can also return a reference to an object,which is what happens here.This method returns a reference to an object of class Soup1.
The classes Soup1 and Soup2 show how to prevent direct creation of a class by making all the constructors private.Remember that if you don't explicitly create at least one constructor,the default constructor(a constructor with no arguments)will be created for you.By writing the default constructor,it won't be created automatically.By making it private,no one can create an object of that class.But now how does anyone use this class?The preceding example shows two options.In Soup1,a static method is created that creates a new Soup1 and returns a reference to it.This can be useful if you want to do some extra operations on the Soup1 before returning it,or if you want to keep count of how many Soup1 objects to create(perhaps to restrict their population).
Soup2 uses what's called a design pattern,which is covered in Thinking in Patterns(with Java)at
www.MindView.net.This
particular pattern is called a Singleton,because it allows only a single object to ever be created.The object of class Soup2 is created as a static private member of Soup2,so there's one and only one,and you can't get at it except through the public method access().
As previously mentioned,if you don't put an access specifier for class access,it defaults to package access.This means that an object of that class can be created by any other class in the package,but not outside the package.(Remember,all the files within the same directory that don't have explicit package declarations are implicitly part of the default package for that directory)However,if a static member of that class is public,the client programmer can still access that static member even though they cannot create an object of that class.