为什么我们不能将一个类定义为 protected
?
我知道我们做不到,但是为什么呢?应该有一些特定的原因。
为什么我们不能将一个类定义为 protected
?
我知道我们做不到,但是为什么呢?应该有一些特定的原因。
Answers:
因为这没有意义。
受保护的类成员(方法或变量)类似于package-private(默认可见性),除了它也可以从子类访问。
由于在Java中没有“子包”或“包继承”这样的概念,因此声明受保护的类或包私有的将是同一回事。
不过,您可以将嵌套类和内部类声明为protected或private。
open
在Kotlin中,它允许在当前程序包之外进行子类化(可以想象protected
在Java中可以避免这种情况,默认情况相反)。
如您所知,默认值是针对程序包级别的访问,而受保护的则是针对程序包级别以及非程序包的类,但这扩展了该类(这里要指出的是,只有在可见的情况下,您才可以扩展该类!)。让我们这样说:
由于没有办法限制仅由少数几个类继承该类(我们不能限制仅在一个包/一个包之外的所有可用类中,只有少数几个类继承该类),因此不使用受保护的访问说明符对于顶级课程。因此,这是不允许的。
@Nikita Rybak的回答有很多要点,但是缺乏细节,我不能在不深入思考的情况下简单地理解这个想法,以下是我的想法,现在我应该完全理解其原因。
四个访问修饰符,假定第一级是公共的,第四级是私有的(基于此表顺序)。我们应该知道的第一件事是为什么不能在顶级将类定义为私有。
因此,如果“私有类foo”(定义的私有成员,即类本身是成员)允许,那么外部(包含该成员)是什么?文件范围?不,文件外部是没有意义的,因为即使单个文件中的多个类也将被编译成单独的类文件。因此,外部是包。但是3级默认访问修饰符已经表示“ package-private ”。因此,将不会使用/不允许使用4级私人访问修饰符。
但是允许嵌套私有类,因为直接外部是类,而不是包,例如:
class PrivateNestedMain {
private static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
现在,如果“受保护的类foo”允许怎么办?受保护的主要特征是子类,因此external(package)应该(由于作用域而定,但仍是可选的)提供子类的样式,即sub-package或package A extends package B
,但我们不知道这种事情。因此,受保护的不能在外部是包的顶层使用最大的潜力(主要作用域是子类范围的)(即没有此类子包的东西),但是受保护的可以在外部是包的嵌套类中使用全部的潜力(即可以是子类):
class ProtectedNestedMain {
protected static class Inner {
public static void main(String[] args) {
System.out.println("Hello from Inner!");
}
}
}
请注意,上述“不能充分利用潜力”是因为它不能达到子类范围,这仅仅是因为没有外部子类,这意味着可以允许实际上受保护,这是避免重复包装工作的唯一选择-private(如果外部不能子类化),请参见下文。
我的困惑主要是由https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html上的著名表引起的:
如果允许第一级(公共)和第三级(打包-私有),那么到底如何不允许第二级(受保护)之间?
公共支持子类如此容易产生误导。读取此表的正确方法是
公共支持子类,如果外部具有子类功能。
同样的误解适用于package-private,package-private不支持子类(单元格中的N)并不意味着子类概念适用于外部。
这意味着如果外部没有子类功能,则我们应该忽略“子类”列:
正如我们现在所看到的,protected和package-private现在都处于同一级别(YYN),对于为什么不允许在中间级别之间再也没有混淆。总体而言,Java只选择package-private而不是protected以避免混淆(这只是选择的问题,但是受保护的主要特征是子类,因此package-private更好),结果是顶层仅允许使用2个访问修饰符:
在顶层(公共或包私有)(无显式修饰符)。
定义受保护的字段将使该字段只能通过继承在包内部和包外部(仅在子类内部)访问。
因此,如果允许我们对一个类进行保护,那么我们可以很容易地在包中访问它,但是要在包外部访问该类,我们首先需要扩展定义该类的实体(即它的包)。
而且由于不能扩展包(可以导入),因此定义一个受保护的类将再次使其变为包私有的,这类似于将其定义为我们已经可以做的默认设置。因此,定义一个私有类没有好处,只会使事情变得模棱两可。
有关更多信息,请阅读为什么外部Java类不能私有或受保护的原因
受保护的:仅对包装级别可见*。
类定义为保护--->无法扩展从外部包(不可见)。
而且,如果无法扩展它,则将其保留为受保护是没有意义的,因为那样它将成为默认值。允许访问权限。
同样适用于私有定义的类。
注意:嵌套或内部类可以定义为protected或private。
*:探索受保护的关键字,为此答案,我使其简洁。
@ Akash5288的答案对我来说毫无意义:
如果所有类都允许子类化,那么它将类似于公共访问说明符。
由于没有办法限制仅由少数几个类继承该类(我们不能限制仅在一个包/一个包之外的所有可用类中,只有少数几个类继承该类),因此不使用受保护的访问说明符对于顶级课程。因此,这是不允许的。
然后,您可以将相同的逻辑应用于受保护的方法和变量,然后它们也“类似于public”。包之外的所有类都可以扩展我们的公共类并使用其受保护的方法。为什么将方法和变量限制在扩展类上可以,但对整个类进行限制却不能呢?“与公众相似”不是“与公众相同”。我的解释是,允许受保护的类是完全可以的,因为允许受保护的方法是可以的。
答案“您不能扩展无法访问/查看的类”更合乎逻辑。
对这个问题有意义的是,JVM是用C(Sun JVM)和C ++(oracle JVM)编写的,因此在编译过程中,我们将从Java文件中创建.class文件,如果我们使用Protected关键字声明了一个类, JVM将无法访问它。
为何JVM无法访问受保护的类的答案是,因为受保护的字段只能通过继承在同一包内访问,也可以通过继承来访问不同的包,而JVM的编写方式却使其无法继承will类。希望这能满足这个问题:)
同样,顶级类也不能是私有的。解释如下:
那么,如果我们将定义一个私有类,该类将只能在定义它的实体(在我们的情况下是它的包)内访问,该怎么办?
因此,定义对类的私有访问将使它可以在默认关键字已为我们使用的同一个程序包中进行访问,因此,将类定义为私有将无益,只会使事情变得模棱两可。
protected表示成员可以被同一包中的任何类以及子类访问,即使它们位于另一个包中。
例:
package a;
class parent{
protected void p();
}
package b;
import a.p;
class child extends parent{
//you can access method which is protected in the parent in the child
}
class another extends child {
//here you can not access the protected method
}