http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6
class C
protected member;
// in a different package
class S extends C
obj.member; // only allowed if type of obj is S or subclass of S
The motivation is probably as following. If obj
is an S
, class S
has sufficient knowlege of its internals, it has the right to manipulate its members, and it can do this safely.
If obj
is not an S
, it's probably another subclass S2
of C
, which S
has no idea of. S2
may have not even been born when S
is written. For S
to manipulate S2
's protected internals is quite dangerous. If this is allowed, from S2
's point of view, it doesn't know who will tamper with its protected internals and how, this makes S2
job very hard to reason about its own state.
Now if obj
is D
, and D extends S
, is it dangerous for S
to access obj.member
? Not really. How S
uses member
is a shared knowlege of S
and all its subclasses, including D
. S
as the superclass has the right to define behaviors, and D
as the subclass has the obligation to accept and conform.
For easier understanding, the rule should really be simplified to require obj
's (static) type to be exactly S
. After all, it's very unusual and inappropriate for subclass D
to appear in S
. And even if it happens, that the static type of obj
is D
, our simplified rule can deal with it easily by upcasting: ((S)obj).member