I have 2 classes, A and B which B inherits from A.
Both classes have a property of type int called w.
In class A w is public and in class B w is private.
I made an object of type A using B constructor - A a = new B()
Yet when i tried to access B's properties i found out i can only access variables or methods from class A even though i made an object of type B.
I thought that this was only relevant if both classes didnt have the same methods or variables.
But in this case both classes have a variable named w yet i can only access the value stored in the A class. Why is this so?
class A
public class A {
public int w;
private static String str = "K";
public A() {
str+="B";
w+=str.length();
str+=w;
}
#Override
public String toString() {
return str.charAt(w-2)+"P";
}
}
class B
public class B extends A {
public static int w = 2;
private String str = "W";
public B(int x) {
w+=super.w;
str+=super.toString()+w;
}
#Override
public String toString() {
return super.toString() + str;
}
}
Testing class
public class Q1 {
public static void main(String[] args) {
A a = new A();
A a2 = new B(1);
System.out.println(a);
System.out.println(a.w);
System.out.println(a2);
System.out.println(a2.w);
B b = new B(2);
System.out.println(b);
}
}
Since the type of variable a is [class] A, the variable can only access members and methods of class A (depending on the access specifiers) – even though the actual type of variable a is class B.
Refer to method paintComponent, in class javax.swing.JComponent. The type of the method parameter is Graphics but the actual type of the parameter is Graphics2D (which extends Graphics). However, in order to access the methods of Graphics2D, you must first cast the parameter, i.e.
Graphics2D g2d = (Graphics2D) g;
This is a fundamental aspect of the object-oriented paradigm.
Refer also to the comment to your question by #ArunSudhakaran
Similarly, if you want variable a to access the w member of class B, you need to cast a.
A a = new B();
if (a instanceof B) {
B b = (B) a;
System.out.println(b.w);
}
If you are using at least Java 14, you can use Pattern Matching for the instanceof Operator
A a = new B();
if (a instanceof B b) {
System.out.println(b.w);
}
Also refer to the book Effective Java by Josh Bloch.
Related
class A
{
private int m;
public void display()
{
System.out.println(m);
}
}
class B extends A
{
int n;
B(int b)
{
this.n = b;
}
public void display()
{
super.display();
System.out.println(n);
}
}
class trial
{
public static void main(String args[])
{
A a = new A();
B b = new B(10);
a = b;
a.display();
}
}
In the above code, how does the variable a on invoking the display() function execute the subclass display() - the subclass display() is of type B and is not supposed to exist in an object with type A. I got this doubt because, apparently superclass variables can reference subclass objects.
However, they will be unable to access elements(variables,functions etc) present in the subclass. But the above code is in violation of that principle.
In your code when the below code is executed
a = b;
variable a refers to a B object. Since A is the superclass of B it can hold the reference of Child Class instance.
It is equivalent to A b = new B(10);
now if we call b.display();
//B's version of display() is called.
This is called Runtime Polymorphism in JAVA. Using which you can override the parent class method in the child object. But you cannot access the instance variable of Child class or the method which is only present in Child Class.
Please read
https://www.geeksforgeeks.org/dynamic-method-dispatch-runtime-polymorphism-java/
I'm new to java. Recently I saw some code which was similiar to this:
class A {
protected int myInt;
public static void main(String[] args) {
B b = new B();
b.myFunction();
}
}
class B extends A {
public void myFunction() {
this.myInt = 10;
}
}
As far as I know, when creating a subclass instance, an instance of its parent is created as well. All protected and public members of base class are accessible from the subclass.
If I override myInt there will be a difference between this.myInt to super.myInt because each class will have its own myInt (B will have access to both).
So, my question is: if I don't override myInt, which form is preferable, this.myInt or super.myInt?
You only need to use this or super when need to specify which scope are you using/referring to. In your case, I'll prefer to omit the this to simplify the readability.
super is used to represents the current instante of a parent class while this is used to represents the current class. You only need to used this or super if some variable or method overlaps (Have the same name) with one in a wide scope.
eg. If you have define a method parameter with the same name as class attribute, you need to use this to indicate that you are using the class attribute and not the method parameter.
public class A {
public int myInt = 1;
public static void main(String[] args) {
B b = new B();
b.myFunction(3);
}
}
class B extends A {
public int myInt = 2;
public void myFunction(int myInt){
System.out.println(myInt); // The parameter
System.out.println(this.myInt); // myInt from the current class (B)
System.out.println(super.myInt); // myInt from the parent class (A)
}
}
This example will print:
3
2
1
If you don't have this kind of collission, the use of this is optional:
public void myFunction2(){
System.out.println(myInt); // Both refers to the same
System.out.println(this.myInt); // variable myInt from class B
}
It's a matter of taste and the project's standards/guidelines more than anything else.
Personally, I wouldn't use either, and would just write myInt = 10.
Only one instance is created. If you instantiate a derived object, the parents constructor is called, but only one object is created. Also, the term this is more so used when there are different variables with the same name being referenced in a class.
For example a simple constructor:
class SupClass{
public int a = 1;
int incA(){
return ++a;
}
}
class MyClass extends SupClass {
public int a = 10;
public int b = 20;
MyClass() {};
MyClass(int a, int b){
this.a = a;
this.b = b;
}
int incA(){
return ++a;
}
public static void main(String args[])
{
SupClass d = new MyClass();
System.out.println(d.a); //1, members known of type SupClass at compile-time,
System.out.println(d.incA()); //11, methods are virtual, decided at run-time
}
}
Only use the super method when you want to explicitly use the value that is in the super class. To answer your question, only methods can be overwritten, member variables can not.
class A
{
int a = 2, b = 3;
public void display()
{
int c = a + b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Why does the output come out as 5,5? And not 5,11?.How would the y.display() method work?
why does the output comes 5,5?
Because A.display() only knows about the fields A.a and A.b. Those are the only fields that any code in A knows about. It looks like you expect the declarations in B to "override" the existing field declarations. They don't. They declare new fields which hide the existing fields. Variables don't behave virtually in the way that methods do - the concept of overriding a variable simply doesn't exist. From the JLS section 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.
You can get the effect you want by changing B so that its constructor changes the values of the existing fields that it inherits from A instead:
class B extends A {
B() {
a = 5;
b = 6;
}
}
Note that these are not variable declarations. They're just assignments. Of course in most code (well, most code I've seen anyway) the fields in A would be private, so couldn't be accessed from B, but this is just example for the purpose of explaining the language behaviour.
In class A you declare fields a and b. The method display uses these fields. In class B you declare NEW fields of the same name. You're actually hiding the old fields not "overriding" them. To assign different values to the same fields use a constructor:
class A {
A(int a, int b) {
this.a = a;
this.b = b;
}
A() {
this(2, 3);
}
int a,b;
public void display() {
int c=a+b;
System.out.println(c);
}
}
class B extends A {
B() {
super(5, 6);
}
}
When doing this:
class B extends A
{
int a = 5, b = 6;
}
you are not redefining a and b, you're creating new variables with the same names. So you end up with four variables( A.a, A.b, B.a, B.b).
When you call display() and calculate the value of c, A.a and A.b will be used, not B.a and B.b
There isn's anything called variable overriding. That is why you are getting the same result in both the cases.
The reason is that Java uses the concept of lexical scope for variable resolution.
Fundamentally, there are two possible options to resolve free variables in a function ('free' means not local and not bound to function parameters):
1) against the environment in which the function is declared
2) against the environment in which the function is executed (called)
Java goes the first way, so free variables in methods are resolved [statically, during compilation] against their lexical scope (environment), which includes:
method parameters and local method variables
field declarations in the class containing method declaration
public field declarations in parent class
and so on, up the chain of inheritance
You would see this behaviour implemented in most programming languages, because it is transparent to developer and helps prevent errors with shadowing of variables.
This is opposite to the way methods work in Java:
class A {
public void foo() {
boo();
}
public void boo() {
System.out.println("A");
}
}
class B extends A {
#Override
public void boo() {
System.out.println("B");
}
}
class Main {
public static void main(String[] args) {
B b = new B();
b.foo(); // outputs "B"
}
}
This is called dynamic dispatch: method call is resolved dynamically in runtime against the actual object, on which it is called.
When you compile your code it pretty much becomes like:
class A extends java.lang.Object
{
int a=2,b=3;
public void display()
{
int c=a+b;
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public void display()
{
super(); //When you call y.display() then this statement executes.
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
And hence, when super calls, the method of class A is being called.
Now go to method of class A. Here int c = a + b; means
c = this.a + this.b; which is 2 + 3.
And the result is 5.
Class B declares variables in B scope, public void display() is part of A class and knows only about its own scope variables.
It's the inheritance functaionality which gives the output 5,5.
Java doesn't have anything like variable overriding. Thus, when the method display() is invoked, it accesses the variables inside the parent class 'A' and not the variables inside the subclass 'B'.
It can be explained with the same reason of why you can't print a variable declared in a subclass (and not in superclass) inside superclass method. The superclass method simply doesn't have access to the subclass variables.
However, you'll be able to print 5,11 if you have accessor methods to the fields in both the classes and you use those accessor methods to get the values instead of directly accessing using variable names. (even if the display() method is present only in superclass). This is because the overridden accessor methods are invoked (in second case) which return the values from the subclass.
Why does the output come out as 5,5? And not 5,11?
Whenever we have same instance variables (applicable to class variable as well) in a class hierarchy, the nearest declaration of the variable get the precedence. And in this case, nearest declaration of a and b from display () method is A’s. So class B’s instance variables go hidden. Hence in both cases, 5 gets printed.
How would the y.display() method work?
Another alternative is to have getter in both classes to get value of a and b.
class A
{
int a = 2, b = 3;
public int getA() {
return a;
}
public int getB() {
return b;
}
public void display()
{
int c = getA() + getB();
System.out.println(c);
}
}
class B extends A
{
int a = 5, b = 6;
public int getA() {
return a;
}
public int getB() {
return b;
}
}
class Tester
{
public static void main(String arr[])
{
A x = new A();
B y = new B();
x.display();
y.display();
}
}
Prints
5
11
class G {
int x = 5;
}
class H extends G {
int x = 6;
}
public class CovariantTest {
public G getObject() {
System.out.println("g");
return new G();
}
public static void main(String[] args) {
CovariantTest c1 = new SubCovariantTest();
System.out.println(c1.getObject().x);
System.out.println(new H().x);
}
}
class SubCovariantTest extends CovariantTest {
public H getObject() {
System.out.println("h");
return new H();
}
}
Output:
h
5
6
Apparently the two println statements in the main method aren't the same. How is the new H() object returned from class SubCovariant's getObject method assigned to a G reference?
G is the declared type, H is the actual type.
The declared type is what you can think of the object as, i.e. G in your example.
The actual type is what the object actually is, i.e. H in your example. This provides actual behaviour, including any which it might inherit from parent classes including G.
When you override a method, it is the type of the instance which matters, not the type of the reference. This is how polymorphism works.
CovariantTest c1 = new SubCovariantTest();
This converts the type of the reference, but not the implementation. if you were to do
System.out.println(c1.getClass());
this would print
SubCovariantTest
so when you call getObject() on this instances, it should be no surprise that this calls SubCovariantTest.getObject()
By comparison, static methods don't follow polymorphism. They cannot be overridden in the same way (they can only be hidden) If you were to make getObject() static in both cases you would find that c1.getObject() would call the matching the type of c1 as the method to call is determined at compile time, not runtime. In fact you can do this.
public class CovariantTest {
public G static getObject() {
System.out.println("g");
return new G();
}
public static void main(String[] args) {
CovariantTest c1 = null;
System.out.println(c1.getObject().x); // prints "g" "5"
}
}
class SubCovariantTest extends CovariantTest {
public H static getObject() {
System.out.println("h");
return new H();
}
}
You can access a null reference here because it is not used at runtime. The compiler only uses the type of the reference, as you might have expected in your question.
I have these two classes:
public class A {}
public class B extends A {}
In the main class, I would declare:
A a = new B();
B b = new B();
What is the difference between a and b ? Is this what we called a subtyping in java?
The difference between a and b is that with a you can only use the public API that the A class provides even though its really a B type object, but with b, you can use both the A's public API as well as B's public API.
For example:
Suppose A and B are defined as follows:
// A.java
public class A
{
public void x()
{
z("X");
}
public void y()
{
z("Y");
}
protected void z(String message)
{
System.out.println(message);
}
}
// B.java
public class B extends A
{
public void a()
{
z("A");
}
public void b()
{
z("B");
}
}
And here's a demo:
// Demo.java
public class Demo
{
public static void main(String[] args)
{
A a = new B();
B b = new B();
// Can only call A's public methods
a.x();
a.y();
// a.a(); Can't use
// a.b(); Can't use
// Can call all public methods
b.a();
b.b();
b.x();
b.y();
}
}
Yes, there is difference between them. Accssibility of methods are different depends on what kind of reference you use.
A a = new B();
B b = new B();
a is a reference of Class A and b is a reference of class B. super class always can be used to point subclass object.
reference a able to access only super class method and properties
reference b able to access super class and it's own method and properties
one important thing is, ability of accessibility of function and properties will decided at runtime.
In below two cases
A a = new B();
a is an instantiation of B and of type A.
whereas in
B a = new B();
a is an instantiation of B and of type B.
The important thing to note here is that (in the first case) if you call a.someMethod(), the method of B will be called, not the method of A (this is called dynamic binding, as opposed to static binding).
This is basic inheritance. In the B b = ... case you can access all methods and variables provided from A and B but in the A case you can only use the methods and variables in the A case.
B gets typecasted into A when it is created, but that information is not required by the compiler.
public class A {
int x;
}
public class B extends A {
int y;
}
A a = new B();
B b = new B();
int c = a.x; //works
int c = a.y; //doesn't work
int c = b.y; //works
int c = b.x; //works
Remember, that you can always cast an object "downwards" in the inheritance chain. But you should not cast a object upwards because the variables for the subclass might be used even though they dont exist, for exmaple B b = new A(); So b.y is dangerous since the B object doesn't have an y variable defined.