Chapter 5 Hide Implementation Process "When the object-oriented design is: How to think about how to change the changed thing." This is especially important for the library. The user (customer programmer) must rely on the part you use and know that once the new version of the library is exported, you don't need to rewrite the code. In contrast, the creator of the library must be free to modify and improve, while ensuring that the customer programmer code will not be affected by changes. To achieve this, you need to comply with certain agreements or rules. For example, when the library programmer is modifying a class within the library, it must be guaranteed that the existing method is not deleted, because the customer programmer code will have breakpoints. However, the opposite situation is painful. For a data member, how can the creator of the library know which data members have been accessed by the customer programmer? If the method belongs to a certain part of a class, it is not necessarily used by the customer programmer, then this pain is equally true. If the creator of the library wants to delete an oldest implementation, and put the new code, what should I do? Any changes to those members may interrupt the customer's code. Therefore, the creator is in an embarrassing situation, and it seems that the fundamental movement must not. To solve this problem, Java launches the concept of "Access Indicators", allowing the library creator to declare which things are available for client programmers, which are not available. This level of access control is between "maximum access" and "minimum access", including: public, "friendly", protected, and private. According to the previous description, you may have summarized as a library designer, you should keep all things as "private), and only show how to use the customer programmer. This idea is completely correct, although it is a bit violates those who use other languages (especially c) programming, those people are accustomed to accessing everything without any restrictions. At the end of this chapter, you should deeply understand the value of Java access control. However, the concept of component libraries and components that can access that library is still not complete. There is still a problem: how to bind components to a single unified library unit. This is implemented through Java's package (package) keyword, and access indicators should be affected by the same package in the same package or in different packages. So at the beginning of this chapter, everyone must first learn how library components are put into the package. This will understand the integrity of the access indicator. 5.1 Package: The library unit We import a complete library with the import keyword, you will get "package". For example: import java.util. *; Its role is imported into a complete utility library, which is part of the standard Java development kit. Since the vector is located in java.util, now you either specify the full name "Java.util.Vector" (can omit the IMPORT statement), or simply specify a "vector" (because IMPORT is default). If you want to import a single class, you can specify the name of the class in the Import statement: import java.util.Vector; now we can freely use the Vector. However, any other classes in java.util are still unused. The reason why this is to be made is to provide a special mechanism to manage the "Name Space". The names of all our members will be isolated from each other.
One method f () located within class A does not conflict with F () of the same "signature" (argument list) located in class B. But will the class name will not conflict? Assume that a Stack class is created, which is installed on a machine that has a Stack class (written by others). What happens? For Java applications in the Internet, this happens when the user doesn't know, because the class will automatically download when running a Java program. It is because there is a potential conflict, so it is especially necessary to complete the namespace in Java, and you need to create a completely unique name, no matter what limit is there. So far, most of this book exist only in a single file, and is designed to be partial (local), no conflict with the same package name (in this case, class name is placed in "default package"). This is an effective practice, and considering the simplification of the problem, the remaining parts of this book will also use it as much as possible. However, if you plan to create a "Internet friendliness" or "suitable for use in the Internet", you must consider how to prevent the reproduction of the class name. When you create a source file for Java, it is usually called an "editing unit" (sometimes called "translation unit"). Each compiler must have a name ending with .java. Moreover, in the inside of the compilation unit, there can be a public class that must have the same name as the file (including the case of case, but exclude .java file extension). If you don't do this, the compiler will report an error. There can be only one public class in each compile unit (the same, otherwise the compiler will report an error). The remaining class (if any) is hidden in front of the world outside the package, because they are not "public" (non-public), and they consist of the "support" class for the main public class. . When compiling a .java file, we will get an exact output file as the name; however, for each class in the .java file, they have a .class extension. Therefore, we will eventually get a large number of .class files in a small number .java file. If you have previously written in the process of compiler, then you may have been used to the compiler to first divide a transition form (usually a .Obj file), use one linker to encapsulate it with other things together (generate a Execute the file), or package it together (generate a library). But that is not a Java's work. A valid program is a series of .class files, which can be packaged and compressed into a JAR file (using JAR tools provided by Java 1.1). The Java interpreter is responsible for searching, loading, and explanation of these files (annotation 1). 1: Java is not forced to use the interpreter. Some of the Java compilers of some intrinsic code can generate separate executables. "Library" is also made up of a series of files. Each file has a public class (not forced to use a public class, but this is the most typical), so each file has a component. If you want to put all these components (they in their own independent .java and .class files), the package keyword can work). If the following code is used in the beginning of a file: package mypackage; then the package statement must appear as the first non-comment statement of the file.
The role of this statement is to point out part of this compilation unit belongs to a library named mypackage. Alternatively, it indicates that it indicates that the public class name in this compilation unit is under the name of MyPackage. If anyone wants to use this name, you either point out the full name or in combination with MyPort key (using the options given earlier). Note that all letters in the name should be lowercase according to the Java package (package), and even those intermediate words are also available. For example, assume that the file name is Myclass.java. It means there is one in that file and can only have a public class. And the name of that class must be myclass (including case in size): package myclass {//........................... The keyword activates the name in MyPackage so that they can be used. Another way is to specify the full name: mypackage.myclass m = new mypackage.myclass (); Import keyword can make it simpler: import mypackage. *; //.. .Myclass m = new myclass (); As a library designer, be sure to remember that the Package and Import keywords allow us to do what we do is dividing a single global namespace, ensuring that we will not encounter the conflict of the name - no matter how many people use the Internet, No matter how many people write their own classes with Java. 5.1.1 Creating a unique bag name You may notice such a fact: Since a package will never really "package" to a single file, it can be composed of multiple .class files, so the situation may be slightly confusing. To avoid this problem, the most reasonable approach is to place all the .class files used in a particular package into a single directory. That is, we must use the hierarchical file structure of the operating system to avoid chaos. This is the method taken by Java. It also solves the other two questions: Create a unique package name and find classes that may be somewhere in the directory structure. As we describe Chapter 2, in order to achieve this, you need to encode the location path of the .class file to the name of the package. But according to the convention, the compiler forces the first part of the package name is the Internet domain name of the creator. Since the Internet domain name is definitely unique (guaranteed by INTERNIC - Note 2, it controls the assignment of the domain name), so if it is acting in this approach, the name of the package will definitely not repeat, so I will never encounter a name conflict. problem. In other words, the conflict of the name will never appear never appear in writing a Java code in the same path name to others. Of course, if you don't have your own domain name, you must create a very unique package (such as your own English name) so that you can create a unique package name. If you decide to issue your own Java code, it is highly recommended to apply for your own domain name, and the cost it needs is very low. 2: ftp: //ftp.internic.net This skill is to resolve the package name into a directory on its own machine. In this way, the Java program runs and needs to load the .class file (this is dynamic, an object that is a target that belongs to that class, or when you first access a Static member of that class), it can be found. The directory where the Class file resides.
The Java Interpreter's work procedures are as follows: First, it is set to set the environment variable classpath (when Java or tools with Java interpretation capabilities - such as browser - install it into the machine). ClassPath contains one or more directories that use special "roots" to expand searches for .class files here. From that root, the interpreter will look for the package, and replace each point (period) to a slash, thereby generating a path name starting from the ClassPath root (so package foo.bar.baz will become FOO / BAR / baz or foo / bar / baz; specifically a forward slash or a backslash is determined by the operating system). They are then connected together to become each entry within ClassPath (entrance). When searching for .class files later, you can start the name corresponding to the class name that is ready to create from these places. In addition, it also searches for some standard directories - these directories are related to where Java interpreter resides. In order to further understand this problem, the following is taken as an example, it is Bruceeckel.com. After coming it over, com.bruceeckel created a unique global name for my class (COM, EDU, ORG, NET and other extensions before the Java package, but since Java 1.2, this The situation has changed. The entire package is now lower-written). Since I decided to create a library called Util, I can further split it, so the final package is named: package com.bruceeckel.util; now, this package name can be used as the "namespace" of the following two files Use: //: Vector.java
// Creating a package
Package com.bruceeckel.util;
Public class vector {
Public vector () {
System.out.println (
"com.bruceeckel.util.vector");
}
} ///: ~
When you create your own package, ask the package statement must be the first "non-comment" code in the file. The second file surface looks similar:
//: List.java
// Creating a package
Package com.bruceeckel.util;
Public class list {
Public List () {
System.out.println (
"com.bruceeckel.util.list");
}
} ///: ~
These two files are placed in a subdirectory in my own system:
C: / doc / javat / com / bruceeckel / util
If you go back from it, you will find the bag name com.bruceeckel.util, but what is the first part of the path? This is determined by the CLASSPATH environment variable. On my machine, it is:
Classpath = .; D: / java / lib; C: / DOC / JAVAT
It can be seen that in the classpath, you can contain a large number of spare search paths. However, pay attention to a problem when using JAR file: The name of the JAR file must be placed in the classpath, not just its path. So for a JAR file called Grape.jar, our classpath needs:
Classpath = .; D: / java / lib; c: /flavors/grape.jar
Once you have properly set a good class path, you can place the following files in any directory (see 3.1.2 "Assignment" in Chapter 3 when performing the program, please refer to Chapter 3.
// Uses the library
Package C05;
Import com.bruceeckel.util. *;
PUBLIC CLASS LIBTEST {
Public static void main (String [] args) {
Vector v = new vector ();
List l = new list ();
}
} ///: ~
After the compiler encounters the Import statement, it searches for the directory specified by the classpath, finds the subdirectory COM / BRUCEECKEL / UTIL, then find the appropriate compiled file (for the vector is vector.class, List.class) . Note that VECTOR and LIST must be set to PUBLIC.
Automatic compilation
When you create an object for the import class (or when accessing a class Static member), the compiler will find the same-name .class file in the appropriate directory (so if an object of class X is created, it should be x.class ). If you only find x.class, it is the class that must be used. However, if it also discovered an x.java in the same directory, the compiler compares the date tag of the two files. If x.java is new than X.class, it will automatically compile X.java, generate a latest X.Class.
For a specific class, or not finding it in the .java file with it, it will take the above processing.
2. Conflict
If two libraries are imported by *, what happens when they include the same name? For example, assume that a program uses the following import statement:
Import com.bruceeckel.util. *;
Import java.util. *;
Because java.util. * Also contains a VECTOR class, this will cause potential conflicts. However, as long as the conflict doesn't really happen, then no problem - this is of course the most ideal situation, because otherwise, you need a lot of programming work to prevent conflicts that may never have.
If you try to generate a vector, you will definitely conflict. As follows:
Vector v = new vector ();
Which VECTOR class is it referenced? The compiler has no answer to this question, and the reader cannot know. So the compiler will report an error to force us to clearly explain. For example, suppose I want to use standard Java Vector, then they must be programmed below:
Java.util.Vector v = new java.util.vector ();
Since it (together with ClassPath), specify the location of the vector, so no longer need Import java.util. * Statement unless you want to use anything from java.util.
5.1.2 Customizing Tool Library
After mastering the aforementioned knowledge, you can start creating your own tool library so that you can reduce or completely eliminate duplicate code. For example, you can create an alias for system.out.println () to reduce the amount of code repeatedly. It can be part of a package called Tools:
//: p.java
// The p.rint & p.rintln shorthandpackage com.bruceeckel.tools;
Public class p {
Public static void rint (Object obj) {
System.out.print (OBJ);
}
Public static void rint (string s) {
System.out.print (s);
}
Public static void rint (char [] s) {
System.out.print (s);
}
Public Static Void Rint (Char C) {
System.out.print (c);
}
Public Static Void Rint (INT i) {
System.out.print (i);
}
Public Static void Rint (long L) {
System.out.print (L);
}
Public static void rint (float f) {
System.out.print (f);
}
Public Static Void Rint (double d) {
System.out.print (d);
}
Public Static void Rint (Boolean B) {
System.out.print (b);
}
Public static void rintln () {
SYSTEM.OUT.PRINTLN ();
}
Public static void rintln (Object obj) {
System.out.println (OBJ);
}
Public static void rintln (string s) {
System.out.println (s);
}
Public static void rintln (char [] s) {
System.out.println (s);
}
Public Static Void Rintln (Char C) {
System.out.println (C);
}
Public Static Void Rintln (INT I) {
System.out.println (i);
}
Public Static void Rintln (long L) {
System.out.println (L);
}
Public static void rintln (float f) {
System.out.println (f);
}
Public Static Void Rintln (Double D) {
System.out.println (d);
}
Public Static Void Rintln (Boolean B) {
System.out.println (b);
}
} ///: ~
All different data types can now be output in a new row (p.rintln ()), or not in a new row output (p.rint ()).
Everyone may guess the directory where this file must start from a ClassPath position, then continue COM / BRUCEECKEL / TOOLS. After compiling, use an Import statement to use the p.class file anywhere in your own system. As follows:
Tooltest.java
So starting from now, whenever you make a useful new tool, you can add it to the Tools directory (or your own Util or Tools directory).
1. ClassPath trap
There is a very interesting trap in the P.java file. Especially for early Java implementations, the correct setting of class paths is usually a very difficult job. When writing this book, I introduced the P.Java file, which seems to be working very normal. However, in some cases, it begins to interrupt. In a long time, I am sure that this is Java or other time to implement an error. But in the end, I finally found a program in a place (ie, chapter 17, the codePackager.java), which uses a different class P. Since it is used as a tool, sometimes it will enter the class path; other will not do this. But as long as it enters the class path, then if the executed program needs to look for class in com.bruceeckel.tools, Java first discovered P. P. of CodePackager.java. At this point, the compiler reports that a specific method is not found. This is of course very headache, because we have seen this method in the previous class P, and there is no more diagnostic report to provide us with a clue, let us know that it is a completely different class ( That is not even public). At first glance, this seems to be an error of the compiler, but if you examine the Import statement, you will find it just say: "There may be P" here. However, we assume that the compiler searches anywhere in your own class, so once it discovers a P, it will use it; if "wrong" is found during the search process, it will stop searching. This is slightly different from us, because there are some annoying classes, they are all in the package. And here there is a P, but can still be found during the conventional classpath search process.
If you encounter such a situation, be sure to ensure that each place in the classpath, each name has only one class.
5.1.3 Using Import Change Behavior
A feature that Java has been canceled is C's "conditional compilation", which allows us to change parameters, have different behavior, and do not change any other code. The reason why Java abandoned this feature may be due to this characteristics often used to solve cross-platform problems in C: Different parts of the code are compiled according to the specific platform, otherwise it cannot be run on a specific platform. Since Java's design ideas are a automatic cross-platform language, this feature is not necessary.
However, there are other very valuable purposes. A very common use is to debug code. Debugging features can be used during development, but there is no such function in the released products. Alen Holub (www.holub.com) proposes the concept of using a package (package) to imitate the concept of conditions. According to this concept, it creates a very useful Java version of the C "concluding mechanism". The reason why we can say "it should be true" or "it should be true" or "it should be fake". If the statement does not agree with you, you can find the relevant situation. This tool is particularly useful during debugging.
Program debugging can be used in this class:
//: Assert.java
// assertion Tool for Debugging
Package com.bruceeckel.tools.debug;
Public class assert {
Private static void perr (string msg) {
System.err.Println (MSG);
}
Public final static void is_true (boolean exp) {
IF (! ");" Assertion Failed ");
}
Public final static void is_false (Boolean Exp) {if (exp) Perr ("Assertion Failed");
}
Public Final Static Void
IS_TRUE (Boolean Exp, String MSG) {
IF (! "" "Assertion Failed: MSG);
}
Public Final Static Void
IS_FALSE (Boolean Exp, String MSG) {
IF (Exp) Perr ("ASSERTION FAILED: MSG);
}
} ///: ~
This class simply encapsulates Boolean test. If fails, an error message is displayed. In Chapter 9, everyone will learn a more advanced error control tool called "violation control". But in this case, the PerR () method can work well.
If you want to use this class, add this line in your own program:
Import com.bruceeckel.tools.debug. *;
To clear the conctructive mechanism so that you can issue the final code, we have created the second Assert class, but it is in a different package:
//: Assert.java
// Turning Off The assertion output Output
// So you can ship the program.
Package com.bruceeckel.tools;
Public class assert {
Public final static void is_true (boolean exp) {}
Public final static void is_false (boolean exp) {}
Public Final Static Void
IS_TRUE (Boolean Exp, String MSG) {}
Public Final Static Void
IS_FALSE (Boolean Exp, String MSG) {}
} ///: ~
Now, if you turn the previous IMPORT statement into the following:
Import com.bruceeckel.tools. *;
The program no longer appears. Here is an example:
//: Testassert.java
// Demonstrating the assertion Tool
Package C05;
// Comment the folowing, and uncomment the
// subsequent line to change assertion behavior:
Import com.bruceeckel.tools.debug. *;
// Import com.bruceeckel.tools. *;
Public class testassert {
Public static void main (String [] args) {
AskERT.IS_TRUE ((2 2) == 5);
AskERT.IS_FALSE ((1 1) == 2);
AskERT.IS_TRUE ((2 2) == 5, "2 2 == 5");
AskERT.IS_FALSE ((1 1) == 2, "1 1! = 2");
}
} ///: ~
By changing the imported Package, we can turn your code from the debug version into the final release version. This technique can be applied to any type of conditional code.
5.1.4 deactivation
Everyone should pay attention to this question: After each package is created, a directory structure is specified for the package time. This package must exist (residing) within the directory specified by its name. And this directory must be able to start searching and discovering from ClassPath. At the beginning, the application of the package keyword may be confusing, because unless it adheres to the rules that specify the package according to the directory path, you will get a lot of inexplicable messages in the runtime, pointing out that you can't find a specific class - - Even the class is clear in the same directory. If you get a message like this, try to mark the package statement as a comment. If you do this, you can know where you are. 5.2 Java Access Indicator
For each definition of each member of the class, Java Access Indicators Poubleblic, Protected, and Private are placed in their top - whether they are a data member, or a method. Each access indicator only controls access to that particular definition. This is significantly different from C . In C , the access indicator controls all of its definitions until it is again added.
Through thousands of inexhaustible contacts, the program specifies some form of access to all things. In the subsequent section, everyone should learn all the knowledge related to all kinds of access. The first start from the default access.
5.2.1 "Friendly"
If you don't specify an access indicator at all, what happens when all the examples before this chapter? Default access There is no keyword, but it is often referred to as "Friendly). This means that all other classes in the current package can access "Friendly" members, but for all classes outside the package, these members are "private", and the outside world is not accessible. Since a compilation unit (a file) can only be from a single package, all classes within a single compiler are automatic "friendly". Therefore, we also say that friendly elements have "package access" permissions.
Friendly Access Allows us to combine related classes into a package to facilitate communication with each other. After combining the class into a package (this allows friendly members to visit each other, that is, let them "make friends"), we "have" the code in that package. Only the code we already have to visiting the other code you have. We can think that friendly access makes it meaningful to make the class in a package, or the front of the latter is the cause of the latter. In many languages, our way we have organized within the document tend to be strong. However, in Java, it is forcibly organized in a very meaningful form. In addition to this, we may sometimes want to exclude some classes, do not want them to access classes defined in the current package.
For any relationship, a very important question is "Who can access our 'Private' or Private Code. Class control which code can access yourself. No secret can be "intrusive". Another package can be declared a new class, then say: "Hey, I am bob friend!", And counting the "protected", friendly and "Private" of Bob. member. To obtain an access authority, the only way is:
(1) Enables members to become "public" (public). Thus all people can access it from anywhere.
(2) Turn into a "friendly" member, the method is to discard all access indicators and placed their classes in the same package. In this way, other classes can access members.
(3) If you introduce "inheritance" concept, you will know, a inherited class can access a protected member or visit a public member (but not accessible for private members). It can only access friendly members when both classes are within the same package. But now you don't have to care about this problem. (4) Provide the Accessor / Variableer method (also known as "acquisition / setting" method) to read and modify the value. This is the most formal method in the OOP environment, as well as the basics of Java Beans - the specific situation will be introduced in Chapter 13.
5.2.2 public: Interface Access
When using the public keyword, it means that the member declaration followed by the public in public applications apply to everyone, especially for customers who apply to the library. Assuming that we define a package called Dessert, which contains the following unit (if you have difficulty in executing the program, please refer to Chapter 3 3.1.2 "Assignment"):
//: cookie.java
// Creates a library
Package c05.dessert;
Public class cookie {
Public cookie () {
System.out.println ("Cookie Constructor");
}
Void foo () {system.out.println ("foo");}
} ///: ~
Keep in mind that cookie.java must reside within a subdirectory named Dessert, and this subdirectory must be located below the C05 directory specified by ClassPath (C05 represents this book Chapter 5). Don't mistake to think that Java will look at the current directory as a search start. If you don't use "." As part of ClassPath, Java will not consider the current directory.
Now, if you create a program that uses a cookie, as shown below:
//: DINNER.JAVA
// Uses the library
Import c05.dessert. *;
Public class dinner {
Public dinner () {
System.out.Println ("DINNER Constructor");
}
Public static void main (String [] args) {
Cookie x = new cookie ();
//! x.foo (); // can't Access
}
} ///: ~
You can create a cookie object because its builder is public, and the class is also public (more detailed description of the public class). However, Foo () members can not access within Dinner.java, because foo () is only "friendly" only in the Dessert package.
Default package
Everyone may be surprised to find that the following code can be successfully compiled - although it seems to have violated the rules:
//: Cake.java
// Accesses a class in a Separate
// compiration unit.
Class Cake {
Public static void main (String [] args) {
PIE X = New Pie ();
x.f ();
}
} ///: ~
In the second file in the same directory:
//: Pie.java
// the Other Class
Class Pie {
Void f () {system.out.println ("PIE.f ()");}
} ///: ~
Originally, they may see them as completely unconnected files, but Cake can create a PIE object and can call its F () method! The usual idea will believe that PIE and F () are "friendly", so it is not suitable for Cake. They are indeed friendly - this part of the conclusion is very correct. But they can still be used in Cake.java because they are located in the same directory, and there is no clear package name. Java regards this file as part of the directory "default package", so they are "friendly" for other files in the directory. 5.2.3 Private: Can't touch!
The Private keyword means that no one can access that member unless the particular class is, and from that class. Other members in the same package cannot access Private members, which makes it seems to isolate classes with us. On the other hand, you cannot create a package from several people. So private allows us to freely change that member while doing care about whether it will affect another class in the same package. The default "friendly" package is usually an appropriate hidden method; please remember that for the package of the package, it is not possible to access a "friendly" member. This effect is often satisfactory because the default access is our usual way. For members who want to turn into a public (public), we usually point out that they can be freely called by the customer programmer. And as a result, you will usually think that you don't have to frequently use the private keyword because you can release your own code without having to use it (this is a stark contrast to C ). However, with the deepening of learning, everyone will find that Private still has very important use, especially when involving multi-threaded treatment (see Chapter 14, see Chapter 14).
Below is an example of applying private:
//: Icecream.java
// Demonstrates "Private" Keyword
Class sundae {
Private sundae () {}
Static Sundae Makeasundae () {
Return new sundae ();
}
}
Public class Icecream {
Public static void main (String [] args) {
//! Sundae x = new sundae ();
Sundae x = sundae.makeasundae ();
}
} ///: ~
This example proves to use Private convenience: sometimes want to control the object's creation, and prevent someone from accessing a specific builder (or all builders). In the above example, we cannot create a sundae object through its builder; instead, you must call the MakeSundae () method to implement (notes 3).
3: Another impact will also generate: Since the default builder is uniquely defined, its attribute is Private, it prevents the inheritance of this class (this is the topic you want to focus on this chapter 6).
If you determine that only one "Assistant" method is, then for any way, you can set them to Private, which guarantees that you will not be able to use it elsewhere in the package to prevent yourself or delete methods. After setting the properties of a method to Private, you can guarantee this option (however, if a handle is set to Private, there is no indication that other objects cannot have a public handle that points to the same object. About the "alias" Will be detailed in Chapter 12).
5.2.4 protected: "A friendly"
Protected Access Indicator requires everyone to know in advance. First of all, pay attention to this fact: to continue to learn this book until the content before inherited, do not necessarily need to understand the contents of this section first. However, in order to maintain the complete content, this still has to be briefly described and provides related examples.
Protected keyword introduced a concept called "inheritance", which is based on existing classes and joins new members, and does not affect existing classes - we will Existing classes are called "basic classes" or "base class". It can also change the behavior of the existing member. For inheritance from an existing class, we say that our new class "extension" has the existing class. As follows:
Class foo extends bar {
Class definition remaining part appears exactly the same.
If you create a new package and inherit from a certain class in another package, the only member that can access is the original PUBLIC member. Of course, if inherited in the same package, the inherited package can access all "friendly" members. Sometimes, the founder of the basic class likes to provide a special member and allows access to derivative classes. This is the work of protected. If the cookie.java file of the 5.2.2 section "Public: Interface Access", then this class cannot access "friendly" members:
//: chocolatechip.java
// can't Access Friendly MEMBER
// in Another Class
Import c05.dessert. *;
Public class chocolatechip extends cookie {
Public chocolatechip () {
System.out.println (
"Chocolatechip constructor");
}
Public static void main (String [] args) {
Chocolatechip x = new chocolatechip ();
//! x.foo (); // can't Access foo
}
} ///: ~
For inheritance, a interesting thing worth noting is if the method foo () exists in class cookies, it will also exist in all classes inherited from cookie. But because foo () is "friendly" in the outside, we can't use it. Of course, it can also turn it into public. But in this way, because everyone can freely access it, it may not be the situation we hope. If you want to modify the class cookie as this:
Public class cookie {
Public cookie () {
System.out.println ("Cookie Constructor");
}
protected void foo () {
System.out.println ("foo");
}
}
Then you can also access foo () in the package dessert, but other things inherited from cookie can also access it. However, it is not public (public).
5.3 Interface and implementation
We usually believe that access control is a way to hide implementation details. After encapsulating data and methods into the class, a data type can be generated, which has its own characteristics and behavior. However, due to two important reasons, access to that data type plus its own boundaries. The first reason is to specify which of the customer programmers can use, which cannot be used. We can build your own internal mechanism in the structure without worrying about the customer programmer as part of the interface, thus free use or "abuse". This reason directly leads to the second reason: we need to separate the interface with the implementation details. If the structure is used in a series of procedures, users can not do anything else outside the publication of the news, we can change all things that do not belong to public (such as "Friendly", protected, and private. Do not require users to make any modifications to their code.
We are now in an object-oriented programming environment, one of which is actually referring to "one type of object", just like "fish" or "bird". These features and behaviors are shared from all objects belonging to this class. "Class" is a description of the appearance and behavior of all objects belonging to this.
In some early OOP languages, such as SIMULA-67, the function of keyword class is to describe a new data type. The same keyword has been applied in most object-oriented programming languages. It is actually the focus of the entire language: the new data type is required to be much more than those "containers" used to accommodate data and methods.
In Java, the class is the most basic OOP concept. It is one of the keywords that do not use bold prints in this book - because there are too many quantities, it will cause serious confusion in the page.
For the sake of clarity, consider creating a class with special styles: Place the public member in the most, follow Protected, friendly, and private members. The benefits of doing this are that the user can read it from the top, and first see the most important content for yourself (ie public member, because they can access the external access of the file) and encounter non-public communiques. After the member stops reading, the latter is already part of the internal implementation details. However, using the annotation document provided by Javadoc (already introduced in Chapter 2), the readability of the code has been largely resolved.
Public class x {
Public void pub1 () {/ *.. * /}
Public void pub2 () {/ *... * /}
Public void pub3 () {/ *.. * /}
Private void priv1 () {/ *... * /}
Private void priv2 () {/ *... * /}
Private void priv3 () {/ *... * /}
Private INT i;
//.
}
Since the interface and implementation details are still mixed, it is only partially easy to read. That is, you can still see the details of the source code - implementation because they need to be saved inside the class. Shows an interface to a class of consumers to actually work in the "class browser". This tool can find all available classes, summarizing all the operations that can be taken (such as which members can be used), and display it in a refreshing and pleasing form. When you read this book, all excellent Java development tools should have launched their own browsers.
5.4 Access
In Java, it is also possible to use access indicators to determine which classes can be used by users of the library. If you want a class that can be called by the customer programmer, a public keyword can be placed somewhere in front of the start of the class main body. It controls whether the customer programmer can create an object belonging to this class.
To control a class access, the indicator must appear before the keyword class Class. So we can use: public class widget {
That is, if our library name is MYLIB, all customer programmers can access widget - through the following statement:
IMPORT MYLIB.WIDGET;
or
IMPORT MYLIB. *;
However, we must also pay attention to some additional limits:
(1) Each compile unit (file) can only have a public class. Each compilation unit has a public interface concept that is expressed by that public class. According to your own needs, it can have any "friendly" classes that provide support. However, if multiple public classes are used in a compiler, the compiler will prompt us an error message.
(2) The name of the public class must be fully consistent with the name of the file containing the compiler, even its case. So for Widget, the name of the file must be widget.java, and should not be widget.java or widget.java. Similarly, if the occurrence does not match, a compile period error will be reported.
(3) May (but common) There is no public class at all of the compilation unit. At this point, you can specify the file name with your own will.
If you have obtained a class inside MyLib, you are ready to complete the task executed by other PUBLIC classes inside the widget or mylib. What happens when it is? We don't want to spend our efforts to prepare documents for customer programmers, and feel that you will make big hand modifications, and delete your own classes, replace it into another class. In order to achieve this flexible handling, it is necessary to ensure that no client programmer can rely on specific implementation details hidden within MYLIB. To reach this, just remove the public key from the class, so that the class becomes "friendly" (class can only be used in the package).
Be careful not to set the class into private (which will cause other things other than the class to access it), and cannot be set into protected (notes 4). Therefore, we now have only two options for the class: "Friendly" or public. If anyone else can access the class, you can set all the builders to Private. In this way, in the case of a Static member of the class, an object (notes 5) belonging to that class is not created in addition to all of themselves. As shown in the following example:
//: Lunch.java
// Demonstrates Class Access Specifier.
// Make a class effectively private
// with private constructors:
Class soup {
PRIVATE SOUP () {}
// (1) Allow Creation Via Static Method:
Public static strong Soup Makesoup () {
Return new soup ();
}
// (2) CREATE A Static Object and
// Return A Reference Upon Request.
// (The "Singleton" Pattern):
Private static soup ps1 = new soup ();
Public static soup access () {
Return PS1;
}
Public void f () {}
}
Class Sandwich {// Uses Lunch
Void f () {new lunch ();
}
{ONLY One Public Class Allowed Per File: Public Class Lunch {
Void test () {
// can't do this! Private constructor:
//! Soup priv1 = new soup ();
Soup priv2 = Soup.makesoup ();
SANDWICH F1 = New Sandwich ();
Soup.access (). F ();
}
} ///: ~
4: In fact, the Java 1.1 internal class can be "protected" or "private", but that is special. Chapter 7 will explain this problem in detail.
5: It can also be implemented by inheritance from that class.
So far, most of our creation is either returning to Void, or returns a basic data type. So in the following definition:
Public static soup access () {
Return PSL;
}
It is the most beginning to make people confuse. Words before the method name (Access) point out what the method returns. Before this, we saw Void, which means "not return" (void is "virtual" in English. But return to the handle of an object, this time is this This method returns a handle that points to an object of the class Soup.
SOUP classes show us how to prevent all builders from private to prevent direct creation of a class. Keep in mind that if you create at least one builder is not explicitly created, you will automatically create the default builder (no argument). If you write the default builder yourself, it will not be created automatically. After turning it into private, no one can create an object for that class. But how do others use this class? The above example reveals two options. The first choice, we can create a Static method, then create a new SOUP, then return to a handle pointing to it. This solution is undoubtedly especially useful if you want to make some additional operations for Soups before returning, or want to know how many SOUP objects created (may be to limit their number).
The second option is to use the Design Pattern technology, which will be described in detail later. Usually the scheme is called "Some Siles" because it only allows you to create an object. The object of class Soup is created into a STATIC Private member, so there is one and there can be only one. It cannot be accessed at all unless you pass the public method Access ().
As early as possible, if an access indicator is set up for the access to the class, it will automatically think "friendly". This means that the object of the class can be created by other classes in the package, but cannot be created outside the package. Keep in mind that all files in the same directory, if the Package declaration is not explicitly made, then they are default a part of the default package of that directory. However, if the attributes of the class a Static member are public, the customer programmer is still able to access That Static member - even if they cannot create an object belonging to that class.
5.5 Summary
For any relationship, the most important point is the boundaries or rules that must be observed in all aspects. When you create a library, it is equivalent to establishing a relationship with the user who is library (ie "customer programmer") - those users belong to another programmer, may use our library to build an app, or use us The library builds a larger library.
If the rules are not developed, the customer programmer can operate all the members of the class as you wish, whether we are willing to do it directly. Everything is exposed in front of others. This chapter tells how to build a class, making an ideal library. First, we tell how to encapsulate a set of classes into a library. Second, we describe how the class controls access to its members.
Under normal circumstances, a C program project begins to interrupt some place between 50K to 100K line code. This is because C has only one "namespace", so the name will begin to conflict with each other, resulting in additional management overhead. In Java, package keywords, package naming schemes, and import keywords provide us with full control of the name, so naming conflicts can be easily avoided.
There are two reasons for we control access to members. The first is to prevent users from taking into contact with those who should not touch. For internal mechanisms of data types, those tools are required. But they are not part of the user interface, and users don't have to use it to solve their own specific issues. Therefore, the method and field becomes "private" (private ", it can greatly facilitate the user. Because they can easily see which is most important for themselves, and what they need to be ignored. This simplifies the user's understanding of a class.
The second one for access control is the most important reason: allowing the library designer to change the internal working mechanism of the class, and don't worry that it will affect the customer programmer. At the beginning, you can build a class with a way, and then find that you need to rebuild the code to achieve a faster speed. If the interface and implementation details have already made a clear separation and protection, you can easily reach your own purpose, and users don't require users to change their code.
Use access indicators in Java to effectively control the category of category. The user of that class knows how to know which is what you can use, which can be ignored. But more importantly, it ensures that no user can rely on any part of the basic implementation mechanism. As a category of categories, we can freely modify the basic implementation details, which will not have any impact on the customer programmer because they cannot access the part of the class.
After the implementation details of the ability to change the basis, in addition to improving their settings, it also has the freedom of "making mistakes". No matter how much it is planned and design, there may still be some mistakes. Since I know that I can make this error quite safely, I can safely carry more and more free tests. This is very helpful to the improvement of our programming level, so that the entire project will eventually be completed faster and better.
A class of public interfaces can be seen in all users, so when analyzing and design, this is the most important part of its accuracy. But you don't have to be too nervous, a little error is still allowed. If there is a little problem in the original interface, you can consider adding more methods, just guarantees that the customer programmer has been used in their code.