java class, extending external API functionality - java

I have an external API (I can't modify it) with class "A" and local class "B" which overrides methods of "A" and adds an additional function.
I need to use one of them according to some parameter "is_A".
/------ API (A.java) -----/
package A;
public class A {
public int pingA( int value ) {
return value;
}
}
/------ my class (B.java) -----/
package B;
import A.*;
public class B extends A {
#Override
public int pingA( int value ) {
return value;
}
public int pingB( int value ) {
return value;
}
public static void main(String[] args) {
final boolean is_A = false;
A obj;
if (is_A) {
obj = new A();
} else {
obj = new B();
}
if (!is_A) {
int n = obj.pingB(3);
}
}
}
In this case I want to use class "B", but the command "int n = obj.pingB(3);" is not compiled because there is no method pingB in A.
The exact message is:
cannot find symbol
symbol: method pingB(int)
location: class A.A

You're adding a new method in a subclass which does not exist in the super class. There is no way to call the new method in the subclass using a reference to the superclass. You'd have to cast to to the subclass type to use the new method.
You could do something like:
A obj = new B();
if (obj instance of B) {
B b = (B)obj;
int n = b.pingB(3);
}
Here B is a A but A is not a B so it doesn't have the pingB(int) method.

You need to cast obj back to B.
if (!is_A) {
int n = ((B) obj).pingB(3);
}
You can by the way better use the instanceof keyword instead of is_A.
if (obj instanceof B) {
int n = ((B) obj).pingB(3);
}

You need to cast to your derived class to be able to call it's methods. Usually that is done with and if( obj instanceof B ) but as you already have a boolean with that information it's going to look like this:
public static void main(String[] args) {
final boolean is_A = false;
A obj;
if (is_A) {
obj = new A();
} else {
obj = new B();
}
if (!is_A) {
int n = ((B) obj).pingB(3);
}
}

obj is still having the type A (-> you declared A obj;) -> this way the type binding does not work for compilation.

Related

Object evaluating in java

I don't understand, why Java acts the way it does.
I have two classes,
Class A:
public class A {
public String s = null;
public A(int s) {
this.s = "a";
}
public A(String s) {
this.s = "b";
}
public int f(A p) {
return 2;
}
}
Class B:
public class B extends A {
public String s = "c";
public B() {
super(null);
}
public B (String s) {
this (0);
this . s = s ;
}
public B (int x) {
super ("d");
this . s = this . s + x ;
}
public int f (A p) {
return 3;
}
public int f(B p) {
return 4;
}
If I know have my main class, in which I run the following code:
public class Test {
Public static main(String[] args) {
B b1 = new B("g");
A ab = new B(6);
System.out.println(ab.f(b1));
}
}
Why am I getting 3 as an result, and not 2 or 4, like I would expect?
Normally I would assume, if I run the method f of the object ab, and give f the object b1 as a parameter, it would either return 2, not compile (since the only method f in Class A uses an Object A and not an Object B) or it would look for another method f in Class B, that uses an Object B as a parameter and would execute that, in which case the program should return 4.
This is the relevant statement
ab.f(b1)
The fact that you are passing the object reference b1 to the method is irrelevant because none of these methods are doing anything with the parameters being passed. The question here is should calling f() return 3 or 2? It will return 3 because are creating an instance of B (A ab = new B(6);) and this class B overrode the f() method.
What is the impact of A ab = new B(6);?
When you instantiate objects using the superclass to the right of the assignment symbol =, you are actually widening the type of the object created (Making an object of a subclass into an object of a superclass). If the subclass have new methods, those methods will be inaccessible to this object. Only methods declared in the superclass are accessible and, through polymorphism, overridden methods are accessible as well (as was already demonstrated by the example above). However, if we were to add a new method to class B
public void newMethod() {
System.out.println("new method");
}
and modified the Test class
public class Test {
public static void main(String[] args) {
B b1 = new B("g");
A ab = new B(6);
System.out.println(ab.f(b1));
ab.newMethod(); // compile error
b1.newMethod();
}
}
newMethod will be inaccessible to instance ab but not to b1. For this reason, the method f(B p) is inaccessible for ab, as you can see in the image below.
I think it calls your f method in class B that returns 3 because, even though b1 is of class B, class B is a subclass of A. Since :
public int f (A p) {
return 3;
}
comes before the other f method, it checks that first. It says is b1 of type A? And the answer is yes, because all Bs are As. So it uses that function, returns 3 and completes the method call.

Java-Can't override the method even though reference object is pointing to the subclass object [duplicate]

This question already has answers here:
Why parent class method is getting called and not child class in this case?
(4 answers)
Closed 4 years ago.
I have another sample program where it does override but all methods have same number of parameters.
class A {
int a;
// function with dummy parameters
void printArray(int i) {
System.out.println("A");
}
}
class B extends A {
//function with dummy parameters
void printArray(int i, int s) {
System.out.println("B");
}
}
public class JavaApplication5 {
public static void main(String[] args) {
A ob = new A();
B o2 = new B();
A o3;
o3 = o2;
o3.printArray(3, 2); // It says that it can not be applied to given type :(
}
}
If you dont want any errors, you need to tell the Java interpreter than o3 is able to call printArray(3,2) by casting. Mainly by doing
((B)o3).printArray(3,2);
Moreover, what you are doing is not overriding anything. (Notice your method paramter in class A and class B is different) Overriding would be something like this:
class A {
int a;
// function with dummy parameters
void printArray(int i){
System.out.println("A");
}
}
class B extends A {
//function with dummy parameters
#Override
void printArray(int i) {
System.out.println("B");
}
}
public class Example {
public static void main(String[] args) {
A ob = new A();
B o2 = new B();
A o3;
o3 = o2;
o3.printArray(3);
}
}
Here you do not need to cast anything since class B overrides the method in class A. As far as the Java interpreter is concerned, any instance of class A AND class B can call printArray, so it doesn't matter if the object o3 is an instance of class A or class B.

Java inheritance fields [duplicate]

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;
}
}

Java cast to superclass and call overload method

abstract class A {
int met(A a) {
return 0;
}
int met(B b) {
return 1;
}
int met(C c) {
return 2;
}
}
class B extends A {
int met(A a) {
return 3;
}
int met(B b) {
return 4;
}
int met(C c) {
return 5;
}
}
class C extends B {
int f() {
return ((A)this).met((A)this);
}
}
public class teste {
public static void main(String args[]) {
C x = new C();
System.out.println(x.f());
}
}
The program will return 3 and I was expecting 0. Why does the first cast in the method f do nothing and the second one works? Is it because in the A and B classes the met methods are overloaded and therefore static binding is used?
That's just the way polymorphism works. Just consider this example:
A a = new C();
a.met(a);
This would as expected call the correct method B#met(...). The method-tables for an object don't just change because you change the type of the variable you stored the Object in, since the binding between an Object and it's methods is stronger than the one between the storage-type and the methods related to it. The second type works, because the type of the input is casted to A and thus the method recognizes it as A (the type of the input-storage has stronger binding than the Object type).

get super class value in java

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).

Categories