views:

253

answers:

4
class BaseClass {
    private void f() {
     System.out.println("Baseclass f()");
    }

    public static void main(String[] args) {
     BaseClass dc = new DerivedClass();
     dc.f();
    }
}

class DerivedClass extends BaseClass {
    public void f() {
     System.out.println("DerivedClass f()");
    }
}

In my opinion, the object dc refers to should have only one non-override method - public void f() method,which make it(the public method) invisible when refered to with BaseClass reference.Since the object dc referes to does not have the private void f() method either because the DeriverClass could not inherit the private method,how could the object dc refers to call method f()?

thanks.

+3  A: 

Just to keep things straight, DerivedClass (DC) DOES inherit private void f() from BaseClass (BC). This inherited method is not accessible to DC but it is there because any method called in the BC part of DC has to have access to all of BC. So when you cast DC to a BC the inherited method becomes available. Now because you are running the code inside of the BC class it can access all of the private members of BC. If you moved the main to DC it shouldn't compile let alone run.

James Keesey
+1  A: 

The main method is inside BaseClass and the private methods are visible to it. If main is in some other class, it will not compile.

vivyzer
+3  A: 

A common(ish) misconception is that private is per instance rather than per class.

For example:

class Foo
{
    private int a;

    public bar(final Foo other)
    {
        other.a = 5;
    }
}

Some people are under the impression that the code above should not work because "a" is "private". That is not the case, any Foo instance can access the private variables/methods of any other Foo instance. "private" just means that instances of other classes (other than Foo in this case) cannot access the private members.

TofuBeer
Why do Java allow this kind of syntax?
Jichao
Because it is technically inside the same scope.
BalusC
c++ does the same... I am not aware of any language that provides protection at the object level (doesn't mean there isn't one, there is a lot I do not know :-).
TofuBeer
It's the case of Ruby : private applies to objects, not classes.In Scala, both visibility levels exist (the syntax is private and private[this])
barjak
+1  A: 

Four points:

(1) To elaborate on what vivyzer wrote, the code compiles because the main method in BaseClass has access to the class's own private methods. If you wrote the code as:

class BaseClass {
  private void f() { }
}

class DerivedClass {
  public void f() { }
}

class Bystander {
  public static void main() {
    BaseClass inst = new DerivedClass();
    inst.f();
  }
}

Then the code would not compile.

(2) This is allowed by the language to support the usecase where the author of a base class can add a new private method without worrying about other authors' derived types.

(3) You won't see this if the method was not private. If the base class's f() had package or protected visibility, then the method would be a virtual method.

(4) The reverse of point #2 is not supported by Java. Specifically, if a derived class has a private method, and a new version of the base type introduces a non-private method with the same signature, the derived class and new base class cannot be used together. There are other languages (for example C#) that addresses these sorts of modular, generational development questions more completely. If you are interested in this aspect, this is a good read on Artima: Versioning, Virtual, and Override

Dilum Ranatunga
class DerivedClass should extends BaseClass.
Jichao