jarosik
jarosik

Reputation: 4564

Protected method call from other package

I thought I understand protected modifier, but it looks like I don't. The example is simple:

package com;
public class Main {

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

and:

package net;

import com.Main;

public class Out extends Main {

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

Why can't I call method1 from a class that extends Main? Compiler error suggest to change modifier to public.

I am really confused.

Upvotes: 3

Views: 5058

Answers (3)

jarosik
jarosik

Reputation: 4564

It looks like you actually can call a method of superclass from different package, you just cant do it explicitly:

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;
    }
}

This class dont implement getMaxNumber(), yet a call rec.getMaxNumber() is OK. That is the actual call to the superclass, right?

The point is: why can't we call methods of superclass from other package on an object with the 'parent' reference type?

Upvotes: 0

ataulm
ataulm

Reputation: 15334

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();
    }

}

The above would work even though getMaxNumberOfPeopleThatICanAccommodate() isn't defined explicitly in Chair, Chair will use the implementation from Seat. The protected modifier allows subclasses to call (or override) the method, and also allows classes from the same package to call the method:

package com.example.furniture;

public class Bed {

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

    private int peopleICanFit() {
        return 2;
    }

}

And classes extending the one with the protected method can override that method too:

package com.example.furniture;

public class ReallySmallChair extends Seat {

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

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

}

But if you try to access the protected method from an external package, it won't work:

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;
    }

}

You'll get a compiler error when trying to access either the seat.get... or chair.get... methods.

If you had a subclass of Seat in a different package, then you could still access the protected methods because it fulfils one of the two conditions (a subclass, or another class in the same package), but only its own method:

package com.example.room;

public class RecreationalVehicle extends Seat {

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

}

That works, because getMaxNumberOfPeopleThatICanAccommodate() is a method that belongs to RecreationalVehicle (it's a subclass). If it tried to access it from a Seat variable, it wouldn't allow it because RecreationalVehicle isn't allowed to touch another instance's protected methods as it's not in the same package:

package com.example.room;

public class RecreationalVehicle extends Seat {

    Seat seat = new Seat();

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

}

would cause a compiler error.

Upvotes: 1

ROMANIA_engineer
ROMANIA_engineer

Reputation: 56626

It doesn't work because you create a Main instance in Out (an Out is a Main, but a Main is not an Out).

It will work if you'll call directly method1:

public Out(){
    method1();
}

or if you have an Out instance:

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

or

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

Here you can find some details ( section 6.6.2 ):

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

Upvotes: 0

Related Questions