0

I have a method dummy with A as class parameter, but i need to pass instance of subclasses B to that method. I know from: Does Java casting introduce overhead? Why? that downcasting in java have overhead. Most of my code deal with subclass B so i dont use downcasting for this purpose. Instead i use temporal instance variable cc for that purpose. But this is not make a change for object of subclass m. I need change in variable cc avaliable too for instance variable m. This is my code:

public class TestCast {

    public TestCast() {
        B m = new B(12, 3);
        dummy(m);
        A cc = m;
        dummy(cc);
        System.out.println(m.a);
        System.out.println(cc.a);
    }

    public void dummy(A t) {
        t.a = 22222;
    }

    public static void main(String[] args) {
        new TestCast();
    }
}

class A {
    public int a = 0;

    public A(int a) {
        this.a = a;
    }
}

class B extends A {

    public int a;
    public int b;

    public B(int a, int b) {
        super(a);
        this.a = a;
        this.b = b;
    }
}

with output

12
22222
Community
  • 1
  • 1
Mohammad Fajar
  • 957
  • 1
  • 12
  • 24

4 Answers4

3

In your particular example, both the parent and child classes declared a field with name a. In this case, the child variable hides the parent variable.

Also, variables/fields are not polymorphic entities like methods. They are accessed by the static type of a reference.

In other words, the field access

A var = new A(10);
var.a; // returns 10

And the field access

A var = new B(1501, 10); 
var.a; // also returns 10

but

A var = new B(1501, 10); 
var.a; // returns 10
((B)var).a; // returns 1501

because you access a on a reference with static type B.

In your method

public void dummy(A t) {
    t.a = 22222;
}

The static type of t is A so you will modify the value of the parent class variable.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • Sorry, what you mean with term `static` in your answer. I try your suggestion in my PC, but it doesn't work. I mean `A a = new A(12)` return `12`, but `a = new B(23,23)` will return `23`. – Mohammad Fajar Sep 13 '13 at 10:49
  • @pisang_ijo Consider reading [this](http://javarevisited.blogspot.ca/2012/03/what-is-static-and-dynamic-binding-in.html) tutorial on static vs dynamic binding. For starters, don't pass the same value to your `B` constructor, it'll be harder to tell which you are getting. Then, do exactly what I did in my answer to see the difference. – Sotirios Delimanolis Sep 13 '13 at 12:26
  • OK i understand now what Is the difference between static and dynamic binding. But for my question above, what is the conclusion, is casting like `A cc = m` created new Object or what? What is the purpose of `=` operator in that statement. – Mohammad Fajar Sep 13 '13 at 18:31
  • @pisang_ijo You are not creating a new object with that statement. You are assigning a reference of type `B` that holds an instance `B` to a variable declared with type `A`. So the variable `cc` will point to the object referenced by `m`. This is valid because `B` extends from `A`. However, on `cc` you cannot call methods of class `B` without casting it because the type `A` doesn't declare such methods. – Sotirios Delimanolis Sep 13 '13 at 18:33
  • Sorry, in my code above: `B m = new B(12,3);` `dummy(m); ` will not change state variable `m`. `A cc = (A) m;` `dummy(cc);` change state variable `cc` but not change state variable `m`. and then statement like `cc.a == m.a ` will `false`. So what you mean with "`So the variable cc will point to the object referenced by m`" – Mohammad Fajar Sep 13 '13 at 18:44
  • @pisang_ijo Reread my answer. The `dummy` method declares a parameter of Type `A` so even if you pass an object of type `B`, it will access the field `a` of the parent type, ie. `A`. That's why it gets modified. The whole issue here is that your field from `B` is **hiding** the inherited field of the same name in the parent class. – Sotirios Delimanolis Sep 13 '13 at 18:46
  • And i really dont understand what you mean `static` term in your answer. Can you give me a concrete code. – Mohammad Fajar Sep 13 '13 at 18:47
  • @pisang_ijo The static type of a reference is its declared type. So in `A a = new B(10, 10)`, the variable `a` is **declared as type `A`, so its static type is `A`**. It's **dynamic type or runtime type is `B`**. – Sotirios Delimanolis Sep 13 '13 at 18:48
1

Casting is telling the compiler that a reference variable is of specific Type at runtime

Prasad Kharkar
  • 13,410
  • 5
  • 37
  • 56
  • can you give a litle suggestion how to complete my task? – Mohammad Fajar Sep 13 '13 at 02:46
  • @user2014314, I'm a little bit confused with your words, can you please be more concrete and cleare? – Prasad Kharkar Sep 13 '13 at 02:48
  • i mean inside class `TestCasting` there area many method that require Subclass `B`. But just one method (i.e `dummy`) require supertype `A`. I avoid to create instance like `A a = new B()` because when deal with method that needed object with type `B`, i must use downcasting. And that make many overhead. – Mohammad Fajar Sep 13 '13 at 02:55
  • @user2014314, I think Sotirios Delimanolis answer gives the reason why you can't do it. and don't worry about the performance. – Prasad Kharkar Sep 13 '13 at 03:03
1

Because B is extending A you do not want to re-define the variable a

In answer to your comment, you code should be something like:

class B extends A {

   public int b;

   public B(int a, int b) {
    super(a);
    this.b = b;
   }
}
Scary Wombat
  • 44,617
  • 6
  • 35
  • 64
  • Most of my code deal with type class `B`. So when I create instance like `B b = new B(12,4)`, and in following line I execute statement like `System.out.println(b.b)`, output will be `0`. So that is required to initialize variable `a` and `b` inside contructor of class `B`. – Mohammad Fajar Sep 13 '13 at 03:16
0

IMO, your example code is not perfect implementation of inheritance. Inheritance enables you re-usability of code. In other words, you don't need to declare int a again in class B.

I need change in variable cc avaliable too for instance variable m:

However, if you want to change in variable cc as well, then declare variables a, b as private/protected in both A and B. And provide setters and getters in both classes. And in class B call super.setA(a) like below.

class B extends A {

    private int a;
    private int b;

    public B(int a, int b) {
        super(a);
        this.a = a;
        this.b = b;
    }

    public setA(int a) {
        super.setA(a);
        this.a = a;
    }
}
kotacc
  • 327
  • 2
  • 12
  • Thanks, but when related with my question `how casting work in java`, can you give me some explanation why in my code above the field of `m` not changed simultaneously when the field of `cc` changed. – Mohammad Fajar Sep 13 '13 at 11:02