2014-09-13 48 views
2

我认为我了解protected修饰符,但看起来好像我没有。 的例子很简单:来自其他包的受保护的方法调用

package com; 
public class Main { 

    protected void method1() { 
     // some code 
    } 
} 

和:

package net; 

import com.Main; 

public class Out extends Main { 

    public Out(){ 
     Main m = new Main(); 
     m.method1(); 
    } 
} 

为什么我不能叫method1从延伸到Main一类?编译器错误建议将修改器更改为public

我真的很困惑。

回答

0

,因为你在创建一个Out例如Main(一OutMain,但Main不是Out)它不工作。

它会工作,如果你直接method1拨打:

public Out(){ 
    method1(); 
} 

,或者如果你有一个Out实例:

public Out(){ 
    Main m = new Main(); 
    ((Out)m).method1(); 
} 

public Out(){ 
    Out m = new Out(); 
    m.method1(); 
} 

Here你可以找到一些详情(第6.6.2节):

对象的受保护成员或构造函数可以从仅在负责实现该对象的代码声明的包中进行访问。

+0

第一个代码示例不是一种方法。它在Java中称为'constructor'。这很清楚。他可以用我的一个构造函数替换他的构造函数,一切都可以正常工作。 – 2014-09-13 08:46:38

+0

'方法1()'在一个名为'Out'的类中不是构造函数 – ataulm 2014-09-13 08:47:24

+0

'public Out()'=一个公共构造函数; 'method1()'=方法调用;我认为一切都很清楚。他可以直接调用'method1',因为它是从Main继承的受保护的方法。 – 2014-09-13 08:49:29

0
package com.example.furniture; 

public class Seat { 

    public boolean canAccommodate(int numberOfPeople) { 
     return numberOfPeople <= getMaxNumberOfPeopleThatICanAccommodate(); 
    } 

    protected int getMaxNumberOfPeopleThatICanAccommodate() { 
     return 4; 
    } 

} 


package com.example.furniture; 

public class Chair extends Seat { 

    public boolean willBreakIfNumberOfPeopleSittingExceeds(int numberOfPeople) { 
     return numberOfPeople > getMaxNumberOfPeopleThatICanAccommodate(); 
    } 

} 

以上会即使getMaxNumberOfPeopleThatICanAccommodate()Chair明确定义的工作,Chair将使用实施从Seat。所述protected修饰符允许子类调用(或覆盖)的方法,并且还允许类从同一个包调用的方法:

package com.example.furniture; 

public class Bed { 

    public boolean canFitMorePeopleThanThis(Seat seat) { 
     return peopleICanFit() > seat.getMaxNumberOfPeopleThatICanAccommodate(); 
    } 

    private int peopleICanFit() { 
     return 2; 
    } 

} 

并且延伸至与受保护的方法中的一个类可以覆盖该方法太:

package com.example.furniture; 

public class ReallySmallChair extends Seat { 

    public boolean willBreakIfNumberOfPeopleSittingExceeds(int numberOfPeople) { 
     return numberOfPeople > getMaxNumberOfPeopleThatICanAccommodate(); 
    } 

    @Override 
    protected int getMaxNumberOfPeopleThatICanAccommodate() { 
     return 1; 
    } 

} 

但是如果你试图从外部包访问受保护的方法,它不会工作:

package com.example.room; 

public class LivingRoom { 

    Seat seat = new Seat(); 
    Seat chair = new Chair(); 

    public boolean canAccommodate(int numberOfPeople) { 
     int maxAccommodate = seat.getMaxNumberOfPeopleThatICanAccommodate() + 
       chair.getMaxNumberOfPeopleThatICanAccommodate(); 

     return numberOfPeople <= maxAccommodate; 
    } 

} 

你会得到一个编译器尝试访问seat.get...chair.get...方法时出错。

如果您在不同的包中有Seat的子类,那么您仍然可以访问受保护的方法,因为它满足两个条件之一(一个子类或同一个包中的另一个类),但只有它自己的方法:

package com.example.room; 

public class RecreationalVehicle extends Seat { 

    public boolean canAccommodate(int numberOfPeople) { 
     return numberOfPeople <= getMaxNumberOfPeopleThatICanAccommodate();    
    } 

} 

这工作,因为getMaxNumberOfPeopleThatICanAccommodate()属于RecreationalVehicle(它的一个子类)的方法。如果试图从一个Seat变量访问它,它不会允许它,因为RecreationalVehicle不允许触碰另一实例的保护方法,因为它不是在同一个包:

package com.example.room; 

public class RecreationalVehicle extends Seat { 

    Seat seat = new Seat(); 

    public void foo() { 
     seat.getMaxNumberOfPeopleThatICanAccommodate();    
    } 

} 

会导致编译器错误。

0

看起来你实际上可以调用从不同的包超的方法,你都无法做到这一点明确:

package com.example.room; 

import com.example.furniture.Seat; 

public class RecreationalVehicle extends Seat{ 

RecreationalVehicle rec = new RecreationalVehicle(); 

public boolean canAccomodate(int numberOfPeople){ 

    int n = rec.getMaxNumber(); 

    getMaxNumber(); 
    return true; 
    } 
} 

这个类不实现getMaxNumber(),但调用rec.getMaxNumber()是好。 这是对超类的实际调用,对吧?

问题是:为什么我们不能在其父类引用类型的对象上调用其他程序包 的超类方法?

+0

这不应该作为回答发布,因为它不是你的问题的答案。在@curiosu的答案最后发布的引言解释了 - 只有当它被包含在该包之外的[protected方法]时,_only_才被代码声明,该代码负责实现该对象**。子类负责实现,所以即使子类在另一个包中,它也可以调用超类中的方法。 – ataulm 2014-09-14 17:20:46

+0

在上面的代码示例中,您甚至可以访问RecreationalVehicle _field_的_private_成员,因为您在RV类中,而私有修饰符允许在类中进行访问。 Seat类不在此范围内 - RV不能更改或修改Seat类。这有点微妙的区别:/ – ataulm 2014-09-14 17:24:11

相关问题