Naming of the package
Package names should avoid conflicts with other packages, so choosing a name that is both meaningful and unique is an important aspect of package design. However, programmers around the world are developing packages, and there is no way to know who used what package name, so choosing the only package name is a problem. If we determine that a package is only used within our organization, we can have an internal arbiter to ensure that there is no name conflict between projects.
But for the whole world, this approach is not practical. Package identifiers are all simple names, and a better way to ensure that the package name is to use an Internet domain name. If the company we are working in is Magic.lnc and the company's domain name is magic c.com, then the declaration of the attribute package should be:
package com.magic.attr; Note that the domain name constituent elements here are arranged in reverse order of the conventional domain name.
If we adopt this idiom, the package names we use will not conflict with anyone else's except for the possible conflict within our organization. If there is indeed a conflict within our organization (probably a large enterprise), then we can use more specific domain names to further qualify. Many large companies have internal subdomains, such as east and europe, which can be used to further qualify the name of the package:
package corn.magic.japan.attr;
Using this solution may make the package name very long, but it is relatively safe. Programmers using this technique will not choose the same package name, and programmers who do not use this technique will not choose the name we use.
Package access
When declaring accessibility of top-level classes and top-level interfaces in packages, there are two options: package access (package) and public access (public). Classes or interfaces modified with public can be accessed by out-of-package code, while types not decorated with public have package scope: they can be accessed by other codes in the same package; but they are hidden for out-of-package codes, even in subpackage codes. When declaring types, we should only declare those types that other programmers need to use as public, and hide those types that belong to the implementation details of the package. This technology provides us with great flexibility, and since programmers do not rely on these types of implementation details that they cannot access, we can freely change them when we want to change implementation details.
Class members that are not declared as public, protected or private can be accessed directly by any code inside the package, but are hidden from outside the package. In other words, the default access modifier is "package", with the exception of the members of the interface, and their default access modifier is "public".
Fields or methods that are not declared private within a package can be accessed by all other code in that package, so classes in the same package are considered "friendly" or "trusted". This allows us to define an application framework that combines predefined code and placeholder code, where the placeholder code is overridden by a subclass of the framework class. Predefined codes can use package access modifiers so that other collaborative codes within the package can directly access them, but for out-of-package users, these codes are inaccessible. However, the subpackages of the packages where these codes are located are not trusted and vice versa. For example, code modified with the package access modifier in the package dit cannot be accessed by the code in its child package dit.dat, and vice versa.
Therefore, each type defines three different contracts:
Accessibility and cover method
Only methods that are accessible in superclasses can be overwritten in subclasses. If a method in the superclass cannot be accessed, the method cannot be overridden in the subclass even if the method in the subclass has the same name as the method. When a method is called at runtime, the system considers its accessibility and thus determines which implementation of it is running.
The following specially constructed example is explained more clearly. Suppose we declare an Abstract-Base class in the P1 package:
package P1; {Ab Ab AbAb public abstract class AbstractBase private void pri() {print("stractBase.pri()"):} void pac () {print("stractBase.pac()");} protected void pro() {print("stractBase.pro()");} public void pub() {print("stractBase.pub()");} public final void show() pri(); pac(); pro(); pub(); } }In this class, we define 4 methods, each with a different access modifier, and the body of the method only identifies itself. The method show calls these 4 methods on the current object in turn. When applying this method to different subclass objects, it can explain which implementation of these methods is called.
Now, we define the class Concretel, which extends the AbstractBase class, but is located in the P2 package:
package P2; import P1.AbstractBase public class Concretel extends AbstractBase{ public void pri(){print("Concretel.pri()");} public void pac(){print("Concretel.pac()");} public void pro(){print("Concretel.pro()");} public void pub(){print("Concretel.pub()");} }The 4 methods in the superclass are redeclared in this class and their implementations are changed, which are reporting that they belong to the Con-cretel class. At the same time, their access rights have been changed to public for other code to access. Execute the following code
new Concretel().show():
The following output will be generated:
AbstractBase.pri() AbstractBase.pac() Concretel.pro() Concretel.pub()
Because the private method pri cannot be accessed by subclasses (or other classes), the show method always calls the implementation of the pri method in the AbstractBase class. The pac method with package access permissions in the AbstractBase class cannot be accessed by Concretel, so the implementation of the pac method in the Concretel class cannot override the definition in the AbstractBase class, so the show method calls the AbstractBase.pac method. The pro method and the pub method are both accessible in the Concretel class and can also be overwritten, so the show method calls the implementation of these two methods in the Concretel class.
Follow our foot meaning class Concrete2 to extend the class Concretel, and then we put it in the same package P1 as the AbstractBase class':
package P1; import P2.Concretel public class Concrete2 extends Concretel{ public void pri(){print("Concrete2.pri()");} public void pac(){print("Concrete2.pac()");} public void pro(){print("Concrete2.pro()");} public void pub(){print("Concrete2.pub()");} }Because methods in Concretel have public access rights, they can be accessed in Concrete2, and each method in Concrete2 covers its corresponding methods separately. In addition, since Concrete2 and AbstractBase are in the same package, the method AbstractBase.pac can also be accessed in Concrete2, and the method Concrete2.pac can be overridden. Call the show method on the Concrete2 object, and the print result is as follows:
AbstractBase.pri() Concrete2.pac() Concrete2.pro() Concrete2.pub()
Finally, we define the class Concrete3 to extend the class Concrete2 and put it in package P3:
package P3 import P1.Concrete2; public class Concrete3 extends Concrete2{ public void pri(){print("Concrete3.pri()");} public void pac Q{print("Concrete3.pac()");} public void pro(){print("Concrete3.pro()");} public void pub(){print("Concrete3.pub()");} } Call the show method on the Concrete3 object, and the printing result is as follows: AbstractBase.pri() Concrete3.pac() Concrete3.pro() Concrete3.pub()Here method Concrete3.pac looks like it overrides the inaccessible AbstractBase.pac method, but in fact, method Concrete3.pac overrides the method Concrete2.pac, and method Concrete2.pac overrides the method AbstractBase.pac, so method Concrete3.pac indirectly overrides the method AbstractBase.pac. By redeclaring the pac method in class Concrete2 as having public access permissions, it can be accessed and overwritten by any subclass. '