子类访问父类中用protected修饰的成员
一直记得java类中用protected修饰的成员是可以让子类访问的,但一直没实际去操作一下。今天发现原来虽然子类可以访问父类的protected成员,但还是不能用在子类中实例化一个父类对象的方式去访问protected成员,需要使用this.x或this.x()的形式或者实例化子类去访问(x代表成员变量或方法)
然而,静态的用protected修饰的成员变量或成员方法又可以直接用类名.x或者类名.x()或者实例化的父类对象去访问。
今天做Thinking in java的习题的时候又碰到了一个关于protected类型的内部类的问题,在这里一起记录一下。
题目是第9章 inner class 的Exercise 6。要求在第一个包里创建一个interface,里面至少包含一个方法。在第二个包里创建一个类,这个类需要包含一个protected类型的内部类,并且这个内部类要实现在第一个包里创建的接口。在第三个包里要创建一个类,继承第二个包里的那个类,并且写一个方法创建一个第二个包里的内部类的对象,将这个对象向上转型成第一个包里的接口并返回。以下是我写的代码:
一:接口Input,代表 输入设备
1 package innerclass.exercise6; 2 3 public interface Input { 4 void inputInstruction(String s); 5 }
二:类Computer,里面有一个protected修饰的Mouse内部类(代表鼠标),并且Mouse实现Inout接口
package innerclass.exercise6.other; import innerclass.exercise6.Input; public class Computer { protected int i = 2; protected class Mouse implements Input { @Override public void inputInstruction(String s) { System.out.println("execute "+s); } } }
三:类Lenovo,继承Computer类,在getComputetMouse()方法里试图创建一个Computer.Mouse对象,并向上转型为Input并返回。
package innerclass.exercise6.another; import innerclass.exercise6.Input; import innerclass.exercise6.other.Computer; public class Lenovo extends Computer { Input getComputerMouse() { this.i++; Input computerMouse = this.new Mouse(); return computerMouse; } public static void main(String[] args) { Lenovo lenovo = new Lenovo(); lenovo.getComputerMouse().inputInstruction("open fire"); } }
本以为没啥问题,但
Input computerMouse = this.new Mouse();
这一行却飘红了,idea提示“'innerclass.exercise6.other.Computer.Mouse' has protected access in 'innerclass.exercise6.other.Computer'”
这我就很疑惑了,Lenovo作为Computer的子类,也能够正常访问同样是protected类型的成员变量i,甚至我可以单单声明一个Mouse类型的变量(但不实例化),为啥一
调用Mouse的构造方法就报错呢?
后来看了别人的答案才发现,给Mouse加一个public的构造方法就可以了。原来,类的构造方法的访问权限默认是和类的访问权限一致的,由于Mouse是protected的访问
权限,它的默认构造函数也就是protected的访问权限,而Lenovo和Mouse既不处于同一个包中,又不是Mouse的子类,自然是无法访问Mouse的protected权限的构造方
法的。所以要想在Lenovo中得到一个Mouse的对象,就需要自己给Mouse加一个public访问权限的构造方法。
至于可以在Lenovo里单单声明一个Mouse类型的变量,我认为是可以把Mouse和i一样看作是Computer的成员变量,Lenovo作为Computer的子类,自然可以访问到Computer
的protected权限的成员变量Mouse。(当然,这只是我自己这样理解的,内部类跟成员变量应该还是有不同的吧)
另有一个知识点提一下,只有内部类才能用private或者protect去修饰,一般的类是只有public或者package(默认)访问权限的。