包的命名
包的名字应该避免与其他包冲突,所以选择一个既有意义又唯一的名字是包设计的一个重要方面。但是全球的程序员都在开发包,根本就没有办法获知谁采用了什么包名,因此选择唯一的包名是一个难题。如果我们确定某个包只在我们的组织内部使用,那么我们就可以让内部仲裁者(internal arbiter)来确保项目之间不会发生名字冲突。
但是对于整个世界而言,这种方法是不实际的。包的标识符都是简单的名字,一种比较好的能够确保包名唯一的方法是使用Internet域名。如果我们所就职的公司的名字为Magic.lnc,该公司的域名为magi c.com,那么属性包的声明就应该是:
package com.magic.attr; 注意,这里的域名构成元素是按常规域名的倒序排列的。
如果我们采用这种惯用法,那么除了在我们的组织内部可能会产生冲突外,我们所采用的包名就不会与其他任何人的包名冲突了。如果我们的组织内部确实产生了冲突(可能是大型的企业),那么我们可以使用更具体的域名来进一步限定。许多大型公司都有内部子域名,如east和europe,可以使用这样的子域名来进一步限定包的名字:
package corn. magic.japan.attr;
使用这种方案可能会使包的名字变得很长,但是相对比较安全。使用这种技巧的程序员不会选择相同的包名,而不使用这种技巧的程序员也不会选择我们所采用的名字。
包的访问
在声明包中的顶层类和顶层接口的可访问性时,有两种选择:包访问权限(package)和公共访问权限(public)。用public修饰的类或接口可以被包外的代码所访问,而没有用public修饰的类型则具有包作用域:它们可以被同一个包中的其他代码所访问;但对于包外的代码,甚至是子包中的代码,它们都是隐藏的。我们在声明类型时,应该只把其他程序员需要使用的那些类型声明为public的,而隐藏那些属于包的实现细节的类型。这种技术给我们提供了极大的灵活性,由于程序员并不依赖于这些他们所不能访问的实现细节的类型,所以当我们想改变实现细节时,可以自由地改变它们。
没有被声明为public,protected或private的类成员可以被包内的任何代码直接访问,但对包外的代码是隐藏的。换句话说,默认的访问修饰符是“package",但接口的成员例外,它们的默认访问修饰符是“public" .
在包内没有声明为private的字段或方法可以被该包中的所有其他代码所访问,因此,同一个包中的类都被认为是“友好的”或“可以信任的”。这样就使得我们可以定义组合了预定代码(predefined code)和占位符代码(placeholder code)的应用框架,其中占位符代码被框架类的子类覆盖。预定义代码可以使用包访问权限修饰符,这样包内的其他相互协作的代码就可以直接访问它们,但对于包外用户,这些代码是不可访问的。然而,这些代码所在包的子包是不被信任的,反之亦然。例如,在包dit中用包访问权限修饰符修饰的代码不能被其子包dit.dat中的代码所访问,反之亦然。
因此,每种类型都定义了三种不同的契约:
可访问性和及盖方法
只有在超类中可以访问到的方法才可以在子类中被覆盖。如果超类中的某个方法不能被访问,那么即使子类中的方法与该方法同名,在子类中也不能覆盖该方法。当某个方法在运行时被调用时,系统会考虑它的可访问性,从而决定运行它的哪一个具体实现。
下面这个特意构建的例子解释得更加清楚。假设我们在P1包中声明了一个Abstract-Base类:
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(); } }
在这个类中,我们定义了4个方法,每个方法都具有不同的访问权限修饰符,且方法体都只是标识其自身。方法show在当前对象上依次调用了这4个方法,当把该方法应用于不同的子类对象时,就可以说明到底调用了这些方法的哪个实现。
现在,我们定义类Concretel,这个类扩展了AbstractBase类,但是位于P2包中:
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()");} }
在该类中重新声明了超类中的4个方法,并改变了它们的实现,这些实现在报告它们属于Con-cretel类。同时,它们的访问权限都被改成了public,以便其他代码访问。执行下面的代码
new Concretel().show():
将产生如下输出:
AbstractBase.pri() AbstractBase.pac() Concretel.pro() Concretel.pub ()
因为私有方法pri不能被子类(或其他类)所访问,所以show方法总是调用AbstractBase类中的pri方法的实现。AbstractBase类中的具有包访问权限的pac方法不能被Concretel访问,因此Concretel类中的pac方法的实现不能覆盖AbstractBase类中的定义,故show方法调用的是AbstractBase.pac方法。pro方法和pub方法在Concretel类中都是可以访问的,同时也可以被覆盖,所以show方法中调用的是Concretel类中的这两个方法的实现。
接卜采我们足义类Concrete2,来扩展类Concretel,然后我们把它和AbstractBase类放到同一个包P1中':
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()");} }
因为Concretel中的方法都具有public访问权限,所以在Concrete2中都可以访问到,而且Concrete2中的每一个方法分别对其相应的方法进行了覆盖。此外,因为Concrete2和Ab-stractBase在同一个包中,所以在Concrete2中也可以访问到方法AbstractBase.pac,并且可以覆盖方法Concrete2.pac。在Concrete2对象上调用show方法,打印结果如下:
AbstractBase.pri() Concrete2.pac() Concrete2 .pro() Concrete2.pub()
最后,我们定义类Concrete3来扩展类Concrete2,并放在包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()”);} } 在Concrete3对象上调用show方法,打印结果如下: AbstractBase.pri() Concrete3.pac () Concrete3.pro() Concrete3.pub()
在这里方法Concrete3.pac看起来是覆盖了不可访问的AbstractBase.pac方法,但实际上是,方法Concrete3.pac覆盖了方法Concrete2.pac,而方法Concrete2.pac覆盖了方法AbstractBase.pac,因此方法Concrete3.pac间接地覆盖了方法AbstractBase.pac。通过在类Concrete2中重新把pac方法声明为具有public访问权限,可以使其能够被任何子类所访问和覆盖。'
本文向大家介绍解析Go语言编程中的struct结构,包括了解析Go语言编程中的struct结构的使用技巧和注意事项,需要的朋友参考一下 struct和C语言的很相似,模拟出class的功能,但是不完全的!没有构造函数等! struct的申明 go指针操作 如下我们要对数值进行改变,先要取内存地址,然后再内存地址上改变他的引用 匿名结构 (1)匿名内部结构的使用 (2)匿名类值不需要数据名称、在赋值
我正在使用Maven开发独立应用程序。我尝试了以下场景:1。它使用maven shade插件解包所有的依赖项,这样我的签名JAR(bcprov-jdk16-1.46.jar)就被解包了。因此丢失了JAR的标志,因为am收到安全异常“JCE无法验证提供者BC”。2.使用maven assembly插件(基于assembly.xml)和maven jar插件(为所有jar设置类路径),实现了将所有依赖
据我所知,命名空间std包含所有的C++标准库,其中一个标准库是iostream,它有对象cout和cin。 上面的结构正确吗?还是不同?
本文向大家介绍浅析Java编程中类和对象的定义,包括了浅析Java编程中类和对象的定义的使用技巧和注意事项,需要的朋友参考一下 1,什么是类? 答:类是客观存在的,抽象的,概念的东西。 2,什么事对象? 答:对象是具体的,实际的,代表一个事物。例如:车是一个类,汽车,自行车就是他的对象。 关于类与对象的描述:类是对象的模版,对象是类的一个个体。 3,Java中定义类的方法? 4,对象的定义方法?
本文向大家介绍详解JavaScript编程中的数组结构,包括了详解JavaScript编程中的数组结构的使用技巧和注意事项,需要的朋友参考一下 数组对象的作用是:使用单独的变量名来存储一系列的值。 创建数组, 为其赋值: 实例 什么是数组? 数组对象是使用单独的变量名来存储一系列的值。 如果你有一组数据(例如:车名字),存在单独变量如下所示: 然而,如果你想从中找出某一辆车?并且不是3辆,而是30
10.6. 包和命名 在本节中,我们将提供一些关于Go语言独特的包和成员命名的约定。 当创建一个包,一般要用短小的包名,但也不能太短导致难以理解。标准库中最常用的包有bufio、bytes、flag、fmt、http、io、json、os、sort、sync和time等包。 它们的名字都简洁明了。例如,不要将一个类似imageutil或ioutilis的通用包命名为util,虽然它看起来很短小。要