protected访问修饰符详解

protexted访问修饰符,应该是访问修饰符中最难理解的一个修饰符.一般称之为受保护的访问权限.

其简单理解为protected修饰的成员对于本包和其子类可见.

但这不太够,往下可以引申为两点:

  • 基类的protected成员是包内可见的,并且对子类可见;
  • 若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。

解释:

  • 在一个引用类,和被引用类在一个包的时候,protected成员是可见的(不管是不是子类)

  • 子类如果不在一个包中,子类不能访问基类的protexted成员,但可以访问继承自基类的protexted成员

    形象的解释一下这话,假设你知道你父亲私房钱放在什么地方.当你和你父亲住在一起的时候,你可以去拿你父亲的私房钱用,此时这个钱,根属于你的父亲(你母亲如果知道你父亲私房钱的地址也可以去拿来用),但是如果一旦你们分家,你和别的人组成了新的家庭,你就不可以直接去父亲家里拿钱用了.你能用的,只有你父亲给你的钱,也就是你继承的钱,这时候这个钱是根属于你的.

  • 受保护,这三个字特别有意思,个人感觉,protected关键字的目的是为了保护数据只在同包和子类中能够被访问引用.就像是钱,这个玩意,只能一家人或者你的子女能够用,如果子女分家了,他们只能用自己继承了的钱.绝对不会有外人能够花这笔钱.

如何判断可不可用

光知道上面的定义,还不够,我们必须要还得了解怎么去判断,方法是:

  • 确定出该protected成员来自何方,其可见性范围是什么,然后就可以判断出当前用法是否可行了

实例

这有几个网上的例子,我做了部分的修改,我们可以来分析一下

例子1

package family1;
public class Father {
    protected void Money() {}    // 父类Father1中的protected方法
}

package family1;
public class Son1 extends Father{}

package family1;
public class mother {
    public static void main(String[] args) {
        Son1 son1 = new Son1();
        son1.Money(); // Compile OK     ----(1)
        son1.clone(); // Compile Error     ----(2)
        
        Son2 son = new Son11();    
    	son2.Money(); // Compile OK     ----(3)
   		son2.clone(); // Compile Error     ----(4)
}

    
package family2;
public class Son2 extends Father{}
  • 首先来看 (1)为什么成立? son1的Money,追溯到根源,是谁的钱?是father的钱.那问题来了,father和mother是一family1的中的.所以mother当然可以用father的money啊.所以(1)是成立的

  • (3)和(1)是同理,虽然 son2 和mother不在一个family了,son2找到了老婆,但son2的money不是自己找的,是来源于father的,所以mother当然能用了.

  • (2)为什么错? 首先 clone()方法object中的方法.所以任何类都继承于object.那为什么(2)错呢?mother和son1在一个family中,都继承了clone,但mother是去那了son2的clone,但clone最终来源并不是和mother在一个family.有点绕

    搞个形象的解释.你父亲分别给了你和你兄弟没人一万块.结果你兄弟用完了钱,直接过来就把你的一万块给拿走了,你能够干?很明显不能,这钱是父亲给你的,你兄弟凭啥给你拿走,对吧?同理在(2)中 son2 的clone()是object给的,又不是mother给的,mother凭啥拿啊,就像你二舅要拿你爷爷给的压岁钱,你能给他?

  • (4)同理与(2)

例子2

package family1;
class father {
    protected Object clone() throws CloneNotSupportedException{
       return super.money();
    }
}
 
package family2;
public class son extends father {
    public static void main(String args[]) {
       father fa = new father();
       fa.money(); // Compile Error         ----(1)
 
       son s = new son();
       s.money(); // Complie OK         ----(2)
    }
}
  • 看这里例子,首先为什么(1)错误.解释是:若子类与基类不在同一包中,那么在子类中,子类实例可以访问其从基类继承而来的protected方法,而不能访问基类实例的protected方法。不够简单易懂,但是我们可以从另一个想一下,如果你现在没钱了,但你father有钱,那咋办呢?去找father要啊,但你要怎么去要money呢?

    如果你直接把你father喊过来(实例化father对象),然后对他说,老头子,快给点钱花花,他能给吗?比不可能给啊

  • 那要咋办呢?也就是第二种方法,你先明确自己的地位,自己是个son(实例化自己),然后好声好气的跟father要钱。也就是第二种方法,所以(2)是对的

  • 二者的区别在于(1)方法是将自己当做外人,而(2)方法是将自己作为一家人。

  • 需要注意的是,也可采用super.money去要钱,也是可以的

上一篇:简单的了解一下MVC


下一篇:访问修饰符(public,private,protected,internal,sealed,abstract)