Explain odd scope behavior?

K

kk_oop

This seems like odd Java behavior. Can someone explain the logic
behind it.

Condider these classes:

public class Base
{
public void printText()
{
printName();
}

protected void printName()
{
System.out.println("I am Base!");
}
}

public class Derived extends Base
{
protected void printName()
{
System.out.println("I am Derived!");
}
}

//main class
public class FirstClass
{

public static void main(String[] args)
{
Derived der = new Derived();
Base base = new Base();

System.out.println("Should be base");
base.printText();
System.out.println("\nShould be derived");
der.printText();
}
}

As I would expect, der.printText prints "I am Derived!" However, if I
make printName private in the Base class, der.printText prints "I am
Base!" Why is that? Clearly, Derived's printName is still in scope to
Base's printText. What's going on here?

Thanks for any info,

Ken
 
T

tzvika.barenholz

private methods cannot be overridden, regardless of whether or not a
derived class has a method with the same name and signature.
Think of it as if Derived's printName was actually renamed printName1.
The effect is just the same.
 
K

kk_oop

private methods cannot be overridden, regardless of whether or not a
derived class has a method with the same name and signature.
Think of it as if Derived's printName was actually renamed printName1.
The effect is just the same.

I wonder why they chose that approach. If someone wanted a private
method to not be overridden, they could just make the method final.
Then the compiler would ensure it does not get overriden.

In my example above, if someone (like me) didn't know better and tried
to override a private method, they would not find the bug until run
time. For that matter, I wonder why the compiler lets you try to
override a private method.

Anyway, thanks much for the info!

Ken
 
K

kk_oop

private methods cannot be overridden, regardless of whether or not a
derived class has a method with the same name and signature.
Think of it as if Derived's printName was actually renamed printName1.
The effect is just the same.

This is interesting. After reading your response, I did some research,
and some sources say that the compiler will flag an error if you try to
override a private method. Here's an excerpt from Bruce Eckel's
thinking in Java (see http://www.codeguru.com/java/tij/tij0071.shtml):

"Any private methods in a class are implicitly final. Because you
can't access a private method, you can't override it (the compiler
gives an error message if you try). You can add the final specifier to
a private method but it doesn't give that method any extra meaning."

Other sources say the compiler will not flag this as an error (even
thought the private method will not be overriden). My 1.4 compiler
does not flag the error. That seems like a big flaw to me, as it can
lead to some nasty run-time bugs. Any thoughts as to whether my Java
compiler has a bug, i.e., should it be flagging the private override
attempt as an error?

Thanks again,

Ken
 
C

Chris Smith

I wonder why they chose that approach. If someone wanted a private
method to not be overridden, they could just make the method final.
Then the compiler would ensure it does not get overriden.

A private method is part of the implementation of a class. If it could
be overridden, then:

1. Since it could be overridden, you'd have to be careful not to
override it unintentionally:

2. In order to be careful in that way, the base class would have to
document the names of all of its private methods, just to be sure you
don't pick one by accident, and therefore break the base class.

That makes private methods no longer private. If you want a method to
be able to be overridden, just make it protected and you've accomplished
your goal.

This also has implications for backward compatibility. If I publish a
non-final class, then I might expect that users (who I don't even know)
extend it with subclasses in their software. If I then publish a later
version and add a private method, then their code (which may declare
private methods) might accidentally override one of my private methods,
and all chaos breaks loose causing all manner of inexplicable problems.
This means that after publishing a class I can't add any more private
methods, and that seems to be a very limiting restriction.

Perhaps this is less obvious if, like many C++ programmers, you don't
think of there being a limited contract between a superclass and its
subclasses. There is, though, and there has to be in order to avoid
base class fragility, which is a limiting factor for good OO design in
C++ and other older OO languages.

--
www.designacourse.com
The Easiest Way To Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
B

Bjorn Abelli

This is interesting. After reading your response, I did some research,
and some sources say that the compiler will flag an error if you try to
override a private method. Here's an excerpt from Bruce Eckel's
thinking in Java (see http://www.codeguru.com/java/tij/tij0071.shtml):

"Any private methods in a class are implicitly final. Because you
can't access a private method, you can't override it (the compiler
gives an error message if you try). You can add the final specifier to
a private method but it doesn't give that method any extra meaning."

I would guess Eckel simply has jumped to the conclusion that since private
methods implicitly are final, it would produce the same error as with final
methods that are public or protected.
Other sources say the compiler will not flag this as an error (even
thought the private method will not be overriden). My 1.4 compiler
does not flag the error. That seems like a big flaw to me, as it can
lead to some nasty run-time bugs.

But here I think *you're* jumping to conclusions...

If the base class has "private" methods, the subclasses can't reach them,
right? They're even not *visible* to the subclass!

So why would it then be possible to *override* something that a subclass
can't even see?
Any thoughts as to whether my Java
compiler has a bug, i.e., should it be flagging the private override
attempt as an error?

I would say *not*.

A private method is "invisible" to the derived class, and it would rather be
an error of the compiler to flag for it.

Think of a pre-compiled package that you want to make use of. You don't have
the source code, and the API only states the public and protected methods
(since the private methods anyway are only accessible from objects of the
base classes).

Now you want to extend one of these classes with a sublass of your own with
a method "nothingToDo()".

If the base class in that package now would happen to have such a method
you'd get an unexpected compiler error!

I would not like it to behave that way.

Don't play with other classes private parts... ;-)

// Bjorn A
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top