Re: Difference between compile time and runtime reference/objects
"lielar" <lielar@gmail.com> wrote
I have the following code
-------------------------------------------------
interface I {
int i = 0;
}
It's bad practice to declare member variables in an interface. There's even a
name for the practice: the Constant Interface Antipattern.
The purpose of an interface is to define behavioral contracts, not implementation.
class A implements I {
int i = I.i + 1;
Fugly.
Consider defining instance variables as private nearly always. You need an
affirmative justification to relax the visibility even to package-private, as
you've done here.
This instance variable 'i' hides the superinterface static variable 'i'.
}
class B extends A {
int i = I.i + 2;
This instance variable 'i' hides the superclass instance variable 'i'.
static void printAll(A obj) {
System.out.println(obj.i);
}
public static void main(String [] args) {
B b = new B();
A a = new B();
printAll(a);
printAll(b);
}
}
Matt Humphrey wrote:
You have 2 instance variables both called i, which is almost always a
mistake. printAll() selects the instance variable based on the compile-time
type of the expression, so it always hits the one in A.
The principle here is that variables do not override, only methods do.
<http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.3>:
If the class declares a field with a certain name,
then the declaration of that field is said to hide any and all accessible
declarations of fields with the same name in superclasses,
and superinterfaces of the class.
That explains the value of Matt's advice:
You can make printAll print '2' for B by allowing it dispatch through
object. You don't have to overload any methods to do this.
1) add getI () { return i; } to class A
2) replace the duplicate declaration of "i" in B with i = I.i + 2 in its
constructor
3) Make printAll use the method
System.out.println (obj.getI ())
--
Lew