This question already has answers here:
Is there a way to override class variables in Java?
(17 answers)
Overriding member variables in Java ( Variable Hiding)
(13 answers)
Closed 5 years ago.
I am not able to understand the following output.
I don't know why the output is 10, I think the line A a = new B() creates a new instance of class B, I think the result should be 20
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
Why this works like this .. please explain.
First, see Hiding Fields (emphasis added)
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different
In other words, this isn't "inheritance" since you're actually hiding A's i behind B's i, and you are using a reference object of A, so you are getting its fields. If you did B b = new B(), you would see 20, as expected.
If you expect true overrides, try using methods.
class A {
public int get() {
return 10;
}
}
class B extends A {
#Override
public int get() {
return 20;
}
}
See
A a = new B();
System.out.print(a.get()); // 20
If you really want to see both at once, see this example.
class A {
int i = 10;
}
class B extends A {
int i = 20;
#Override
public String toString() {
return String.format("super: %d; this: %d", super.i, this.i);
}
}
And
A a = new B();
System.out.print(a); // super: 10; this: 20
In java you cannot override an instance variable. The output you are getting is expected. In Java you can only override instance methods and not instance variables.
If you want 20 as an output you may use getter methods over those instance variables.
class A {
int i = 10;
int getI() {
return i;
}
}
class B extends A {
int i = 20;
int getI() {
return i;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.getI());
}
}
Polymorphism is not applicable for fields in Java.Evaluating Variables decision is taken at compile time so always base class variables are accessed.
Because you define 2 variables: one in the subclass B, and one with the same name in superclass A.
A a = new B();
a.i; // refers to A.i
If you cast the A to a B, it will access B.i:
System.out.println(((B)a).i);
I think you need to use 1 variable:
class A {
int i;
public A() {
i = 10;
}
}
class B extends A {
public B() {
i = 20;
}
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i); // will print 20
}
Member variable i is already defined in class A.
In order to achieve what you are looking for, change the class B as shown below:
class B extends A {
public B() {
i = 20;
}
}
Related
Can someone explain why the output is 10 and not 20?
Why does the object refers to the value of the parent class instead of the class it is assigned to?
class A {
int i = 10;
}
class B extends A {
int i = 20;
}
public class MainClass {
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
}
}
The instance you're creating is of type A, so since both variables have the same name, you'll get the superclass' one, if you want B's you should do
B b = new B()
System.out.println(b.i)
You shouldn't use variables of the same name like that in between superclasses and subclasses, gets very confusing and kinda defeats the purpose of inheriting.
In Java, methods are overridden not variables. So variables belong to their owner classes. a is a reference of type A that point to an object of type B but remains of type A.
To call the i of B, you have to cast a to B.
A a = new B();
System.out.println(((B)a).i);
Can someone explain why the output is 10 and not 20?
Since the value of i is defined in the class A and is NOT overridden/re-assigned by the definition of class B as you might just be assuming. Adding a custom constructor could clarify your doubts further of what you might be intending to do:
class A {
int i = 10;
}
class B extends A {
public B() {
this.i = 20;
}
}
A a = new B();
System.out.println(a.i); // would now print 20
Declaring the same variable i in class B would have its own scope and does not inherit from the class A.
Variables can not be overridden in Java as they are resolved at compile-time; You can use super to set its values,
class A {
int i = 10;
}
class B extends A {
int i = 20;
public B() {
super();
super.i = i;
}
}
A a = new B();
System.out.println(a.i); //20
I have created 3 classes, one superclass "a" and under a two subclasses "b" and "c". I am creating an instance of c, give it an integer "n" and then use subclass b to do some calculation. The problem I am having is that when I create an instance c to call b, the data technically belong to the superclass a/c right? so when i create an instance of b with
b b_instance = new b();
inside the instance of c,
the b calc() function I call would return 0. I guess it's because b has it's own eco-sphere of data?
How do I do this?
2)
Also, how do i call the superclass function of the same name?
Thanks!
public class prog
{
public static void main(String args[])
{
c c1 = new c();
c1.run();
}
}
class a
{
private int number;
void set_number(int n)
{
number = n;
}
int get_number()
{
return number;
}
int calc()
{
return number*2;
}
}
class b extends a
{
int calc()
{
// calling the superclass function calc, then subtract
return super.calc() - get_number();
}
}
class c extends a
{
void run()
{
set_number(1);
b b1 = new b();
System.out.println(b1.calc());
}
}
infinite loop problem
public class prog
{
public static void main(String args[])
{
c c1 = new c();
c1.run();
}
}
class a
{
void calc_a()
{
System.out.println("") ;
}
void calc_b()
{
calc_a(); // meaning the calc_a() in the superclass
}
}
class b extends a
{
void calc_a()
{
super.calc_b();
}
}
class c extends a
{
void run()
{
b b1 = new b();
b1.calc_b();
}
}
b b_instance = new b();
inside the instance of c, the b calc() function I call would return 0.
I guess it's because b has it's own eco-sphere of data?
How do I do this?
A "couple" of possible ways. I'd consider extending c from b, this way c gets all the functionality of a and b, something like...
class c extends b {
void run() {
set_number(1);
System.out.println(calc());
}
}
IF, however, this is not feasible (for some reason or other), then you need to pass the value that c has to b, something like...
class c extends a {
void run() {
set_number(1);
b b1 = new b();
b1.set_number(get_number());
System.out.println(b1.calc());
}
}
Now, having said that, this "smells" to me. What's the point of extending from a just so c can perform b? It would set off alarm bells to me.
The problem is, if your call c#calc, it's just going to a's calc method ... which, based on run, doesn't seem to be what you want to achieve, so it's all just a big mess
2)
Also, how do i call the superclass function of the same name?
Because calling calc directly would cause a StackOverflowError because you're constantly calling yourself.
In this case, you're taking the operation that a is doing and making a modification to it. This is a common practice in OO languages.
Side notes...
Java (and the Java community) already have a well defined set of coding practices. You should take the time to learn them, it will make your code easier to read and make it easier for you to read other peoples codes.
Start with Code Conventions for the Java TM Programming Language
Class names should start with a capital letter and methods are in camelCase, for example...
class A {
private int number;
void setNumber(int n) {
number = n;
}
int getNumber() {
return number;
}
int calc() {
return number * 2;
}
}
Updated...
class a {
void calc_a() {
System.out.println("");
}
void calc_b() {
calc_a(); // meaning the calc_a() in the superclass
}
}
class b extends a {
void calc_a() {
super.calc_b();
}
}
class c extends a {
void run() {
b b1 = new b();
b1.calc_b();
}
}
The question you need to ask yourself is, why does b need to override calc_a? Why not override calc_b? It would solve the issue
how do i override it?
class b extends a {
//void calc_a() {
// super.calc_b();
//}
#Override
void calc_b() {
super.calc_b();
}
}
I tried this:
class protectedfinal
{
static abstract class A
{
protected final Object a;
}
static class B extends A
{
{ a = new Integer(42); }
}
public static void main (String[] args)
{
B b = new B();
}
}
But I got this error:
protectedfinal.java:12: error: cannot assign a value to final variable a
{ a = new Integer(42); }
^
1 error
How to work around this problem?
Some people suggested here to use a constructor but this works only in some cases. It works for most objects but it is not possible to reference the object itself from within the constructor.
static abstract class X
{
protected final Object x;
X (Object x) { this.x = x; }
}
static class Y extends X
{
Y () { super (new Integer(42)); }
}
static class Z extends X
{
Z () { super (this); }
}
This is the error:
protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
Z () { super (this); }
^
One could argue that it does not make much sense to store this kind of reference, because this exists already. That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable.
static class Z extends X
{
Z () { super (new Any (this)); }
}
So how can I write an abstract class, which forces all child classes to have a final member which gets initialized in the child?
You have to initialize A.a in its constructor. Subclasses will use super() to pass initializer to A.a.
class protectedfinal {
static abstract class A {
protected final Object a;
protected A(Object a) {
this.a = a;
}
}
static class B extends A {
B() {
super(new Integer(42));
}
}
public static void main (String[] args) {
B b = new B();
}
}
You cannot use this until superclass constructors were called, because at this stage the object is not initialized, even Object constructor hasn't run at this point, therefore calling any instance methods would lead to unpredictable results.
In your case, you have to resolve circular reference with Z class in another way:
Z () { super (new Any (this)); }
Either use a non-final field or change class hierarchy. Your workaround with instance method super(new Any(a())); would not work for the same reason: you cannot call instance methods until superclass constructors were run.
In my personal oppinion, your problems hints towards a flaw in design.
But to answer your question. If absolutly necessary, you can change final fields in java using reflection.
And if everything fails, you can still utilize sun.misc.unsafe.
But I strongly discourage you from doing so, since it potentially kills your vm.
My work around so far is to use methods instead of final members:
class protectedfinal
{
static abstract class AA
{
protected abstract Object a();
}
static class BB extends AA
{
#Override
protected Object a() { return this; }
}
public static void main (String[] args)
{
AA a = new BB();
System.out.println (a.a());
}
}
But I would like to use final members, because I think accessing a final member is faster than calling a method. Is there any chance to implement it with final members?
Why does below code prints "1" ?
class A {
int x = 1;
}
class B extends A {
int x = 2;
}
class Base {
A getObject() {
System.out.println("Base");
return new B();
}
}
public class CovariantReturn extends Base {
B getObject() {
System.out.println("CovariantReturn");
return new B();
}
/**
* #param args
*/
public static void main(String[] args) {
Base test = new CovariantReturn();
System.out.println(test.getObject() instanceof B);
System.out.println(test.getObject().x);
}
}
Because you are referring to fields, which are not affected by polymorphism. If you instead used getX(), it would've returned 2.
What you are asking is, the value of field x defined in class A (because Base.getObject() returns A). Even though CovariantReturn overrides the method to return B, you are not referring to your object as CovariantReturn.
To expand a bit on how fields are not affected by polymorphism - field access is realized at compile time, so whatever the compiler sees, that's what's accessed. In your case the method defines to return A and so A.x is accessed. On the other hands methods are invoked based on the runtime type. So even if you define to return A but return an instance of B, the method you invoke will be invoked on B.
#kris979 Though you are returning B, i think what makes the difference is that the return type is of A. Hence value of x in A i.e. 1 is printed.
As Bozho pointed out - instance variable are never affected by polymorphism. Let me give you a quick small example.
class Base {
int i = 1;
void method() {
System.out.println("in base");
}
}
class Sub extends Base {
int i = 2;
void method() {
System.out.println("in sub");
}
}
public class Test {
public static void main(String[] args) {
Base obj = new Sub();
obj.method();
System.out.println(obj.i);
}
}
This code will print - in sub and 1
I have 2 classes:
public class A
{
int n = 10;
public int getN()
{
return n;
}
}
public class B extends A
{
int n = 20;
public int getN()
{
return n;
}
}
public class Test
{
public static void main(String[] args)
{
B b = new B();
System.out.println(b.getN()); //--> return 20
System.out.println(((A)b).getN()); //--> still return 20.
//How can I make it return 10?
}
}
All methods in Java are always virtual. That is, there is no way of invoking the "super"-version of the method from the outside. Casting to A won't help as it doesn't change the runtime type of the object.
This is probably your best alternative / workaround:
class A {
int n = 10;
public int getN() {
return n;
}
public final int getSuperN() { // "final" to make sure it's not overridden
return n;
}
}
class B extends A {
int n = 20;
public int getN() {
return n;
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
System.out.println(b.getN()); // --> return 20
System.out.println(((A)b).getN()); // --> still return 20.
System.out.println(b.getSuperN()); // --> prints 10
}
}
you can't make the value be "10" because the instance of the object was for class B, and when you do the cast the only thing that are you doing is changing the define class not setting values for the object B, in other words if you need to get 10 its' something like this
b = new A();
That thing won't work due to polymorphism. Class B is still class B even if you cast it into its super class.
I think you'll need something like this:
public class B extends A
{
int n = 20;
/**
* #return the super n
*/
public int getSuperN()
{
return super.n;
}
}
What you see is polymorphism in action. Since b is a B, that method (which returns 20) is always called (regardless if you cast it to an A).