In the below code, why is the super still referring to the subclass variable, and not the super class variable?
class Feline {
public String type = "f ";
public Feline() {
System.out.print("feline ");
}
}
public class Cougar extends Feline {
public Cougar() {
System.out.print("cougar ");
}
public static void main(String[] args) {
new Cougar().go();
}
void go() {
type = "c ";
System.out.print(this.type + super.type);
}
}
What subclass variable? You haven't declared one, so this.type refers to the superclass's variable.
If you declared public String type; in both the superclass and the subclass, it will work the way you are expecting. But right now, the only type variable you've declared is the one on the superclass.
Also, shadowing variables like this is bad practice, as it easily gets confusing as to what type you mean.
Firstly, you don't have subclass variable "type". Hence you are using super(parent) class variable(which is public available for both super and subclass) in the subclass. Hence when you change
type="c"
Super class variable is changed and hence this.type and super.type prints c
Hence in order to get your output, declare "type" in subclass.
public class Cougar extends Feline {
private String type = "f"; //or something else and see the output.
}
When the object of child class is created, the memory is allocated to instance member of the classes in the hierarchies.
There is only one copy in the memory for instance member type that is assigned for super-class but the visibility of that instance variable is public that why you can access it in child class as well using this.type but internally it's same location in the heap that is allocated for that object.
so this.type will change the value of instance member type defined in super class.
Summary: Child class is not defining a new instance member type instead it's inherited from super class.
Read What is purpose of using inheritance?
When type='c' is done in the subclass, it makes the super-class variable hidden, so that the super class variable is no longer available. Hence both this.type and super.type returns the value available ie, 'c', as type='f' is not visible to the code.
At the same time, if we change type='c' to String type='c' here we are creating a local variable, and not overriding the super-class variables. Hence the solution for
public class Feline {
public String type = "f ";
public Feline() {
System.out.println("In 1....feline ");
}
}
public class Cougar extends Feline
{
public Cougar() {
System.out.println("2.....cougar ");
}
public static void main(String[] args) {
new Cougar().go();
}
void go() {
String type = "c ";
System.out.println(this.type + super.type);
System.out.println("Subclass type::"+type);
System.out.println("this.type::"+this.type);
System.out.println("super.type::"+super.type);
}
}
The output is::::::: In 1....feline
2.....cougar
f f
Subclass type::c
this.type::f
super.type::f
In this case a new local variable is created, therefore the super-class variable is not hidden
Related
class Super {
public Integer i = 1;
void Sample() {
System.out.println("method of super class");
}
}
public class Sub extends Super {
public Integer i = 1000;
void Sample() {
System.out.println("method of sub class");
}
public static void main(String args[]) {
Super obj;
obj = new Super();
obj.Sample();
System.out.println(obj.i);
obj = new Sub();
obj.Sample();
System.out.println(obj.i);
}
}
Output:
method of superclass
1
method of subclass
1
When the Sample() method is called we get consequently different outputs (method of super class/subclass)
But when the variable, i is printed, outputs are identical (1)
Are problems the reference/object types or inheritance rules?
Variables in Java do not follow polymorphism and overriding is only applicable to methods, not variables. Thus, you see the overriding behaviour for the method, Sample() but not for the variable, i.
Note that in this case, the child class variable hides the parent class variable and the concept is known as variable hiding.
Note: Always follow the Java naming conventions e.g. you should rename the method, Sample() to sample().
I have 3 classes:
public class Alpha {
public Number number;
}
public class Beta extends Alpha {
public String number;
}
public class Gama extends Beta {
public int number;
}
Why does the following code compile? And, why does the test pass without any runtime errors?
#Test
public void test() {
final Beta a = new Gama();
a.number = "its a string";
((Alpha) a).number = 13;
((Gama) a).number = 42;
assertEquals("its a string", a.number);
assertEquals(13, ((Alpha) a).number);
assertEquals(42, ((Gama) a).number);
}
Member variables cannot be overridden like methods. The number variables in your classes Beta and Gama are hiding (not overriding) the member variable number of the superclass.
By casting you can access the hidden member in the superclass.
Fields can't be overridden; they're not accessed polymorphically in the first place - you're just declaring a new field in each case.
It compiles because in each case the compile-time type of the expression is enough to determine which field called number you mean.
In real-world programming, you would avoid this by two means:
Common-sense: shadowing fields makes your code harder to read, so just don't do it
Visibility: if you make all your fields private, subclasses won't know about them anyway
As a workaround, you can use getter methods:
class A {
private String field = "A: field";
String getField() {
return field;
}
}
class B extends A {
private String field = "B: field";
#Override
String getField() {
return field;
}
}
Java Hiding a field
When successor has a field with the same name as a superclass's field it is called - Hiding a field
Java's field does not support polymorphism and does not take a field's type into account
class A {
String field = "A: field";
String foo() {
return "A: foo()";
}
}
class B extends A {
//B's field hides A's field
String field = "B: field";
String foo() {
return "B: foo()";
}
}
#Test
public void testPoly() {
A a = new A();
assertEquals("A: field", a.field);
assertEquals("A: foo()", a.foo());
B b = new B();
assertEquals("B: field", b.field);
assertEquals("B: foo()", b.foo());
//B cast to A
assertEquals("A: field", ((A)b).field); //<--
assertEquals("B: foo()", ((A)b).foo());
}
[Swift override property]
Please sorry me for that newbie question. This is for my so strange, because before java coding, I have had a C++ background, where variable by default is equal to undefined or null;
So I have a abstract class:
public abstract class Animal {
int lifeBar;
public void eat(int x) {
lifeBar += x;
}
}
And I have Bird class which extends it:
public class Bird extends Animal {
}
And Main class:
public class Main {
public static void main(String[] args) {
Animal bird = new Bird();
bird.eat(10);
System.out.println("bird: " + bird.lifeBar);
}
}
I thought that there should be compilation error, because I didn't declare lifeBar variable, but the console showed me 10. Why is that? Is it because there some default constructor?
Inheritance means subclasses can extends the state of superclass
hence in your example, when Bird extends Animal all the methods and
variables are inherited in Bird class.
lifeBar is an instance variable of type int hence its default value is 0
YOu are calling the method in which lifeBar += x; statement increments the value by 10 because you are passing 10 as argument to method.
lifeBar is member of Animal which isn't initialized explicitly, so it sets its default value that is 0 for int
See
default value of different types
Can you declare an abstract variable type in an abstract class? I am receiving an error when I put this line of code in. I can declare a variable that is final and not final but I am not sure if I should be able to declare a variable that is abstract. What would be the real advantage between an interface and an abstract class?
Error Code:
abstract int myScore = 100; <-- Causes an error
Code:
public abstract class GraphicObject {
int home = 100;
String myString = "";
final int score = 0;
abstract void draw();
abstract void meMethod1();
abstract void meMethod2();
int meMethod3() {
return 0;
}
}
"Can you declare an abstract variable type in an abstract class?"
No, according to the JLS (http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1).
Why should it be abstract if you can't implement variables?
Abstract methods only mean that they must be implemented further in your code (by a class that extends that abstract class).
For variable that won't make any since they keep being the same type. myscore will always be an int.
You may be tinking about override the value of myscore by the class that extends that abstract class.
An abstract method is a method that doesn't have a body. This is because it's meant to be overridden in all concrete (non-abstract) subclasses and, thanks to polymorphism, the abstract stub can never be invoked.
Given the above, and since there is no polymorphism for fields (or a way to override fields at all), an abstract field would be meaningless.
If what you want to do is have a field whose default value is different for every subclass, then you can assign its default value in the constructor(s) of each class. You don't need to make it abstract in order to do this.
No, abstract is used so that methods can only be implemented in subclasses. See http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
You cannot declare an abstract variable in Java.
If you wish to declare a variable in a super-class, which must be set by its sub-classes, you can define an abstract method to set that value...
For example:
public abstract class Foo {
Object obj;
public Foo() {
init();
}
protected void init() {
obj = getObjInitVal();
}
abstract protected Object getObjInitVal();
}
public class Bar extends Foo {
#Override
protected Object getObjInitVal() {
return new Object();
}
}
Base on "AlonL" reply :
You can do this too
public abstract class Foo {
Object obj;
public Foo() {
init();
}
abstract protected void init();
}
public class Bar extends Foo {
#Override
protected void init() {
obj = new Object();
}
}
Please have a look at this code :
class Foo {
public int a;
public Foo() {
a = 3;
}
public void addFive() {
a += 5;
}
public int getA() {
System.out.println("we are here in base class!");
return a;
}
}
public class Polymorphism extends Foo{
public int a;
public Poylmorphism() {
a = 5;
}
public void addFive() {
System.out.println("we are here !" + a);
a += 5;
}
public int getA() {
System.out.println("we are here in sub class!");
return a;
}
public static void main(String [] main) {
Foo f = new Polymorphism();
f.addFive();
System.out.println(f.getA());
System.out.println(f.a);
}
}
Here we assign reference of object of class Polymorphism to variable of type Foo, classic polmorphism. Now we call method addFive which has been overridden in class Polymorphism. Then we print the variable value from a getter method which also has been overridden in class Polymorphism. So we get answer as 10. But when public variable a is SOP'ed we get answer 3!!
How did this happen? Even though reference variable type was Foo but it was referring to object of Polymorphism class. So why did accessing f.a not result into value of a in the class Polymorphism getting printed? Please help
You're hiding the a of Polymorphism - you should actually get a compiler warning for that. Therefore those are two distinct a fields. In contrast to methods fields cannot be virtual. Good practice is not to have public fields at all, but only methods for mutating private state (encapsulation).
If you want to make it virtual, you need to make it as a property with accessor methods (e.g. what you have: getA).
This is due to the fact that you can't override class varibles. When accessing a class variable, type of the reference, rather than the type of the object, is what decides what you will get.
If you remove the redeclaration of a in the subclass, then I assume that behaviour will be more as expected.