I discovered something about Java's type system today.
Suppose there are three Java classes, A, B and C. C extends B and B extends A. A is in package p1. B and C are in package p2. A and C are normal public classes, but B is package private. From package p3, can I see that C is a subclass of A?
In other words, given the following classes:
package p1;
public class A {
public void sayHi() {
System.out.println("hi");
}
}
package p2;
class B extends p1.A {
}
package p2;
public class C extends B {
}
Will this code compile (and run)?
package p3;
public class Run {
public static void main(String[] args) {
p1.A c = new p2.C();
c.sayHi();
}
}
Answer in blue on blue text here: Yes, and I wonder what evil tricks I can pull in my public APIs as a result.
Comments
I believe C# stops this from happenings by dissallowing any public classes in an assembly to inherit from private/internal classes. Compiler spits an error about inconsistent access or something (I didn't test, but I remember something along those lines)
Sorry, I cannot see what is wrong.
You could do more control by having class A final - if thats what you want.
Anders
I don't understand how this could lead to "evil tricks". What am I missing?
I also cannot see what is wrong.
Private/internal classes never stoped evil doers. Java offers package sealing to stop evil doers:
Seal package p2 - before the evil class C does its thing.
C# offers Windows to welcome evil doers.
It's not that anything is wrong, I am just drawing attention to a "wrinkle". A wrinkle is something that is only a little out of the ordinary, but which works in a strange way or whose legality is non-obvious. Every complex system has wrinkles, and I enjoy both reading about and finding them.
As for evil tricks... they would be based around treating instances of C as instances of A, when it is not at all clear from the public API that C is an indirect subclass of A.
Greetings,
From what I can tell, C is a subclass of A, albeit indirect. When I look at a javadoc, it lists all the parent classes, all the way to java.lang.Object .
What's the significance of it being indirectly subclassed, and what tricks can result from that ?
In one of my projects, I intentionally designed by base class methods to be static protected, so that the user of the classes had to intentionally subclass the base class to gain access to them.
designed by base class -> designed my base class