Inheritance and static type java - java

I was playing around with classes since I'm learning java syntax and I came across this weird situation. So given a class A and B:
public class A {
public int x() {
return x;
}
}
public class B extends A {
int x = 5;
public int x() {
return x + 2;
}
public static void main(String[] args) {
B b = new B();
System.out.println(b.x());
}
When I execute the main method I get a compile time error that it doesn't find the x variable and it's calling the method from A because the error shows return x instead of return x + 2. Since b's static type is B, why is it looking in A for x?
error: cannot find symbol
return x;
symbol: variable x
location: class A

The class A doesn't know that it will be extended by B, where the x variable will exist.
In order to make this compile, make A.x() abstract and provide implementation within the subclass:
public abstract class A {
public abstract int x();
}
public class B extends A {
int x = 5;
#Override
public int x() {
return x + 2;
}
..
}

When you are creating the Object of class B, it automatically invoke the x() of class A, But x is not initialized in that class. As it is a local variable, it can not be used without initialization. so it is giving an error.
Try the below code, it is working correctly
class A
{
int x =10;
public int x()
{
return x;
}
}
class B extends A
{
int x = 5;
public int x()
{
return x + 2;
}
public static void main(String[] args)
{
B b = new B();
System.out.println(b.x());
}
}

Related

Explanation on overriding variables java inheritance

Can someone explain why the function prints the variable from super and not from the subclass? Class variables cannot be overridden in Java?
class A {
int i = 1;
int fun() {
return i;
}
}
class B extends A {
int i = 2;
}
class Main {
public static void main(String[] args) {
System.out.println(new B().fun());
}
}
This prints out 1 instead of 2.
Because fields declared in the subclass never override fields of the super class.
Overriding is for methods.
If you want to use the i value of the current class, you could introduce getI() a method to provide the i value :
class A {
int i = 1;
int fun() {
return getI();
}
int getI(){
return i;
}
}
And override it in the subclass :
class B extends A {
int i = 2;
int getI(){
return i;
}
}
You are returning the value of i from fun() function . if you want to return the value of override variable from class B need to override that method, as fun method is a part of the super class it is referring i of super class only.
But always remember overriding of variable in java is always a bad idea it may give you unexpected result.
if you still want you can use this way.
class A {
int i = 1;
int fun() {
return i;
}
}
class B extends A {
int i = 2;
int fun() {
return i;
}
}
class Main {
public static void main(String[] args) {
System.out.println(new B().fun()); // this will refer the override i
}
}

In Java how to refer subclass variable without declaring that variable in parent class?

public class MyTest {
public static void main(final String[] args) {
B b = new B();
b.print();
}
}
class A {
private final int x = 5;
protected int getX() {
return x;
}
public void print() {
System.out.println(getX());
}
}
class B extends A {
private final int x = 10;
#Override
protected int getX() {
return x;
}
}
In this example, I need to print subclass value in the parent class.
It is working fine. No issue.
Now it is printing 10.
But I do not want to define that property in the parent class A.
Because in this example this x datatype is very simple. So no issue.
But in real-time I want to use other datatype which may be another Class variable or List<something> which have huge data.
So ultimately I do not wish to store that value in Class A.
Because it is redundant data. It will slow down in my Hibernate thing.
Please let me know, how to achieve this without declaring variable in parent class. But I still need to use subclass variable in parent class.
make abstract your class A and the getX(); method.
public class Test {
public static void main(final String[] args) {
B b = new B();
b.print();
}
}
abstract class A {
protected abstract int getX();
public void print() {
System.out.println(getX());
}
}
class B extends A {
private final int x = 10;
#Override
protected int getX() {
return x;
}
}
and override the toString method in place of your print method
#Override
public String toString() {
return String.valueOf(getX());
}
the final code
public class Test {
public static void main(final String[] args) {
B b = new B();
System.out.println(b);
}
}
abstract class A {
protected abstract int getX();
#Override
public String toString() {
return String.valueOf(getX());
}
}
class B extends A {
private static final int X = 10;
#Override
protected int getX() {
return X;
}
}
you could also define as static your x variable
But as say Andrew Tobilko you can consider also to use an interface if A doesn't represent a stateful entity.
It's certainly the best solution for your case, mix the use of an interface and an abstract class
public class Test {
public static void main(final String[] args) {
B b = new B();
System.out.println(b);
}
}
interface MyInterface {
int getX();
}
abstract class A implements MyInterface{
#Override
public String toString() {
return String.valueOf(getX());
}
}
class B extends A {
private static final int X = 10;
#Override
public int getX() {
return X;
}
}
You need the getX within the parent class, but you don't have information enough to implement this method there.
You can declare this class as abstract and mark the method with abstract as well. Doing that, you are handing the responsibility of method implementation over its subclasses and preventing from parent field declaration.
If the A doesn't describe any state (only actions/methods), you should consider replacing it with an interface. At the current state, it is the case.
You could make the parent class abstract, eliminate the property in the parent class, make getX() abstract, and then leave print() as concrete. Then just use the concrete implementation of getX() in the child class.

Java procedures of extending abstract class

I am not clear about the procedure of extending a class. Given the following piece of code, why the output is 32?
class Rts {
public static void main(String[] args) {
System.out.println(zorg(new RtsC()));
}
static int zorg(RtsA x) {
return x.f()*10 + x.a;
}
}
abstract class RtsA {
int a = 2;
int f() { return a; }
}
class RtsB extends RtsA {
int a = 3;
int f() { return a; }
}
class RtsC extends RtsB {
int a = 4;
}
First off, fields aren't overridden, so all this is equivalent to
public class Rts {
public static void main(String[] args) {
System.out.println(zorg(new RtsC()));
}
static int zorg(RtsA x) {
return x.f()*10 + x.a;
}
}
abstract class RtsA {
int a = 2;
int f() { return a; }
}
class RtsB extends RtsA {
int b = 3;
int f() { return b; }
}
class RtsC extends RtsB {
int c = 4;
}
The implementation of f() for an object of type RtsC comes from RtsB, since that is the lowest-level class that overrides f(), so its implementation is used, and that returns b, which is 3. That's multiplied by 10, and then added to the a from RtsA, since zorg only knows that x is of type RtsA, so that field is used. That's 3 * 10 + 2 = 32.
(Note that the fact that RtsA is abstract didn't come into this at all; that mostly only matters when you have abstract methods to worry about.)

How to override instance variables/methods in main?

I want to access the instance variable x in the super class.
I can't find a syntax for it. Is this even possible?
public class SuperBoss {
int x = 10;
}
public class Boss extends SuperBoss {
int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.x); //prints out 2, I want it to print out 10
}
I've been trying to use the keyword "super" with no success.
It prints out 2 because your declaration of int x = 2 in Boss is hiding the declaration of x in SuperBoss
Normally you would use the super keyword to explicitly access public fields of the superclass, this however won't work from the static context of the main method. You can define a small helper function that will get you the value of the superclass's x
public class Boss extends SuperBoss {
int x = 2;
public int getSuperX() {
return super.x;
}
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.getSuperX()); //prints out 2, I want it to print out 10
}
}
As far as I can tell (and I should probably look in the JLS for the details), it is legal to access a shadowed non-private field with super, but only from within an instance method. So you could do this:
public class Boss extends SuperBoss {
int x = 2;
int getSuperX() {
return super.x;
}
public static void main (String[] args) {
Boss b = new Boss();
System.out.println(b.getSuperX());
}
}
Add getSuperX() method in your Boss class:
public class Boss extends SuperBoss {
int x = 2;
public int getSuperX() {
return super.x;
}
public static void main(String[] args) {
Boss b = new Boss();
System.out.println(b.getSuperX());
}
}
Yes, there is a way. Fields have compile-time binding. What you need is a cast to SuperBoss:
public class SuperBoss {
int x = 10;
}
public class Boss extends SuperBoss {
int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(((SuperBoss)b).x);
}
}
To do what you want, you need to declare x as protected in the superclass, and not attempt to override it in the subclass:
public class SuperBoss {
protected int x = 10;
}
public class Boss extends SuperBoss {
// int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.x);
}
}
In practice, however, there is little need for protected data. It can cause almost as many problems as public data. Better is:
public class SuperBoss {
private int x = 10;
protected int getX() {
return x;
}
}
public class Boss extends SuperBoss {
// int x = 2;
public static void main ( String[] args ) {
Boss b = new Boss();
System.out.println(b.getX());
}
}
What is going on is that the instance variable of Boss is hiding the instance variable of the same name in SuperBoss. You can temporarily cast your instance to the supertype class:
public static void main ( String[] args ) {
Boss boss = new Boss();
SuperBoss superBoss = boss;
System.out.println(boss.x); //prints 2
System.out.println(superBoss.x); //prints 10
}
This is not recommended. For encapsulation reasons, your instance variables should not be visible, ie. should be private/protected. And probably should not have the same name as variables in parent classes.

Java : Using parent class method to access child class variable

I have the following scenario :
public class A {
private int x = 5;
public void print()
{
System.out.println(x);
}
}
public class B extends A {
private int x = 10;
/*public void print()
{
System.out.println(x);
}*/
public static void main(String[] args) {
B b = new B();
b.print();
}
}
On executing the code, the output is : 5.
How to access the child class(B's) variable(x) via the parent class method?
Could this be done without overriding the print() method (i.e. uncommenting it in B)?
[This is important because on overriding we will have to rewrite the whole code for the print() method again]
EDITED
More Clarification :-
The motive of the question is to use the value of a child class private variable from its parent class method. This doesn't require changing the value of the parent class private variable in order to achieve the desired result.
The answers posted here, though, led me to my desired answer, which I have posted below.
(Thanks all for your time and help )
class A {
private int x = 5;
protected int getX() {
return x;
}
protected void setX(int x) {
this.x = x;
}
public void print() {
// getX() is used such that
// subclass overriding getX() can be reflected in print();
System.out.println(getX());
}
}
class B extends A {
public B() {
// setX(10); // perhaps set the X to 10 in constructor or in main
}
public static void main(String[] args) {
B b = new B();
b.setX(10);
b.print();
}
}
EDITED
Below is a general answer using abstract class and method to solve similar scenario:
abstract class SuperA {
protected abstract Object getObj();
public void print() {
System.out.println(getObj());
}
}
class A extends SuperA {
#Override
protected Object getObj() {
// Your implementation
return null; // return what you want
}
}
class B extends A {
#Override
protected Object getObj() {
// Your implementation
return null; // return what you want
}
public static void main(String[] args) {
B b = new B();
b.print();
}
}
After reading all the answers posted here, I got what I was looking for. The following is what I feel is the best answer for my question :
public class A {
private int x = 5;
protected int getX(){
return x;
}
public void print(){
System.out.println(getX());
}
}
public class B extends A {
private int x = 10;
protected int getX(){
return x;
}
public static void main(String[] args) {
B b = new B();
b.print();
}
}
Setting up a protected getter and overriding it is better than overriding the print() method itself, as there could be any other huge method in place of the print method which might need to access the value of the child class variable(s).
To solve your question you have to define the fields in the parent class A like protected (so it will be inherited on the child class) and set the field value x inside the constructor in the child class B. The print method is also inherited from A class so you can invoke it directly from parent class.
I hope this can help you.
public class A
{
// fields declaration
protected int x = 5;
public void print()
{
System.out.println(x);
}
}
public class B extends A
{
public B()
{
// set child x value. The field have been defined in the parent class
x = 10;
}
public static void main(String[] args)
{
A a = new A();
a.print(); // print 5
B b = new B();
b.print(); // print 10
}
}
You can always add it to the constructor:
public class B extends A {
//this line is unnecessary: private int x = 10;
/*public void print()
{
System.out.println(x);
}*/
public B()
{
x=10;
}
public static void main(String[] args) {
B b = new B();
b.print();
}
}
The reason it won't work as you try it is that default values only get evaluated once. So when it's default 5 in A, it stays 5 even though you used default 10 in B.
You should expose a getter for the value you want and override that in the child class.
Like so:
public class A {
private int x = 5;
public void print()
{
System.out.println(getX());
}
protected void setX(int x)
{
this.x = x;
}
protected int getX()
{
return x;
}
}
public class B extends A {
/*public void print()
{
System.out.println(x);
}*/
public B()
{
setX(10);
}
public static void main(String[] args) {
B b = new B();
b.print();
}
}

Categories

Resources