How to handle polymorphism without casting object? - java

class A{
int a;
public int getA(){
return a;
}
public void setA(int a){
this.a=a;
}
}
// Class B extending A class and add one additional variable
class B extends A{
int b;
public int getB(){
return b;
}
public void setB(int b){
this.b=b;
}
}
// this is the main class
class HelloWorld {
public static void main(String[] args) {
A aa;
if(runtime conditon) {
aa= new B();
aa.setA(3);
((B)aa).setB(4);
}
else{
aa= new A();
aa.setA(3);
}
}
}
How to design to solve the above problem without using casting?
sorry for asking the low-level question (I am new to java).

Since class B extends class A you can use a variable of type A to point to a variable of type B.
But if you want to use only one variable of type A (in your case aa) you cannot use a method of class B without casting the object.
Because you have to remember that when you use a variable (in your case type A) that points to a derived type use (in your case type B), you can only use the methods that are defined in class A, the rest are obscured. By casting the object to its true type you can use all of its methods.

Introduce another variable:
B bb= new B();
bb.setA(3);
bb.setB(4);
aa = bb;

Related

super.a = b instead of super(b)

I'm learning the super keyword and accidentally get this, here's an example :
public class A {
double a;
public A (double a) {
this.a = a;
}
}
public class B extends A {
public B (double b) {
super.a = b; //***
}
}
The usual way to do this as in the tutorials is super(b) to reusing its parent constructor, but what is wrong with super.a = b?
There is no "constructor inheritance" in Java. If the super class doesn't have a no-arg constructor, you must explicitly call its constructor (or one of them if there are several). If you don't, you'll get a compilation error.
When you write your class A like this:
public class A {
double a;
public A(double a) {
this.a = a;
}
}
you overwrite the default constructor and in the line this.a = a you are accessing instance variable and setting the values and in class B:
public class B extends A {
public B(double b) {
super.a = b; // ***
}
}
you are trying to access instance variables of Class B through the constructor because super.a in here , the super referes to the constructor and its wrong and throwing the Implicit super constructor A() is undefined. Must explicitly invoke another constructor which means: in Class B its looking for a constructor which has no parameter because you overwrite the default constructor of class and it can't recognize it by calling super.a = b so you have to call the super constructor as a function and in the first line of code:
public class B extends A {
public B(double b) {
super(b);
super.a = b; // ***
}
}

differences between "this" and "super" when accessing inherited members

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.

Java, use correct constructor based on instance

I need my Class C to choose correct constructor based on instance variable. I have basic code shown below. Whenever I create instance of an class B and store it as reference to A. 'Wrong' constructor is used on class C. What are my options to change this if I don't want to use (b instanceOf B) because it is in other package.
Class A {
}
Class B extends A {
}
Class C {
C(A a){...}
C(B b){...}
}
Class Main{
private createClass(String s){
if (...){
return new B();
}
}
public static void main(String[] args){
A b = createClass("s");
new C(b); //--> constructor C(A a) is used but i need C(B b)
}
}
new C(A a) is called, because the b variable is of type A at compile-time. The compiler doesn't know that at Runtime it will hold reference to an instance of B and that's why it binds to the new C(A a) constructor.
In general, I think your should reconsider your design, but if you want to keep it like this, you could at least make the createClass() method Generic and pass the Class<T> of the resuling type:
private <T extends A> T createClass(String s, Class<T> clazz){
if (...) {
return clazz.newInstance();
}
//
}
This will allow you to point out (and easily switch) the type of the result you need:
B b = createClass("s", B.class);
new C(b);
Rather than using two constructors, use single constructor and use if ( a instanceOf B) and cast the object in B to perform all the operations related to class B specifically. like below snippet
Class C {
C(A a){
if(a instanceOf B){
B b =(B) a;
// all the stuff related to B only
}
//common work for both the scenarios
}
}

is there a vitual parameter invocation as there is for virtual method invocation in java? [duplicate]

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

How does casting work in this situation?

So let's say I have two classes.
public class example1 {
private int a;
private String b;
public example1(int a, String b) {
this.a = a;
this.b = b;
}
public int getA() {
return a;
}
public String getB() {
return b;
}
}
public class example2 extends example1 {
public example2(int a, String b) {
super(a, b);
}
#Override
public int getA() {
return 10;
}
}
Now, if I go ahead and cast example2 to type example 1.
example1 a = (example1) new example2(5, "Hi");
What will a.getA() return?
As a further question from that, if example2 looked like this..
public class example2 extends example1 {
public example2(int a, String b) {
super(a, b);
}
#Override
public int getA() {
return getAModified();
}
public int getAModified() {
return 10;
}
}
What would a.getA() return? What happens here, and more importantly why does it happen?
What would a.getA() return?
Will give you the result from example2, since your instantiated using the class example2
What happens here
example1 a = (example1) new example2(5, "Hi");
.
You are creating an instance of type example1 witn of implementation example2. And casting to example1.
Casting shows the use of an object of one type in place of another type. That's it. It won't magically convert the instantiated object to casted.
What will a.getA() return?
will execute the getA() method of example2 i.e. 10.
Even in your second case, it will return 10.
Reason here is method overriding
Its getting decided during runtime, which getA() method is getting called.
Since you are creating an object of Example2, hence in both cases the getA() of Example2 is getting called, its overriding the getA() method of Example1.
You are able to cast the object of Example2 to Example1 as it is parent class but it won't change the fact that the object is actually of Example2.

Categories

Resources