-4

something about this code confuses me. The first print line is 1600. I understand it has something to do with the static class being Car and not Sportscar. But we created the object as a Sportscar, so why isn't the volume field 3500? Thanks.

 public class Car {
 public int volume;

 public Car() { this(1600); }
 public Car(int volume) { this.volume = volume; }
 public String toString() { return "Car:" + volume; }
 }



 public class SportsCar extends Car {
 public int volume;

 SportsCar() { this(3000); }
 SportsCar(int volume) { this.volume = volume; }
 public String toString() {return "SportsCar:"+volume;}
 }



 public class CarApplication {
 public static void main(String [] args) {
 Car car = new SportsCar(3500);

 System.out.println(car.volume);
 System.out.println(car.toString());
 System.out.println(car);
 }
 } 
Bar
  • 196
  • 10
  • http://stackoverflow.com/questions/685300/is-there-a-way-to-override-class-variables-in-java – Rick S Jun 29 '16 at 18:24
  • Please [edit] your post to contain only valid code -- i.e. get rid of the line numbers. – Nic Jun 29 '16 at 19:05

4 Answers4

2

First off, note that when you call the constructor for SportsCar Java will automatically call the default constructor for its parent class, Car. This will set the volume field of the object's parent Car class to 1600.

In Java, there is no polymorphism for fields. So whereas the toString() method inside your SportsCar class always overrides that of its parent (Car) class, the rules for how identically named instance variables are accessed is a little different.

If you are accessing volume from within the SportsCar class then the volume of SportsCar will be used. From outside the class itself (so when you're calling from CarApplication) which instance variable is accessed depends upon the compile-time type of the object in question. Because you declare the type of car to be a Car, the volume value of the parent Car class is used--hence 1600 is printed. If you had instead declared car to be a SportsCar, 3500 would be printed.

Another option would be this:

System.out.println(((SportsCar)car).toString()); 

This will output 3500, since the type of car has been cast to SportsCar.

Fred Vollmer
  • 171
  • 3
  • 9
1

When you declare something in this way:

ParentClass variable = new ChildClass(Args);

The methods and fields in ParentClass are the only ones available to you. It is restricted because you declared the type as a ParentClass. Because Car's volume is 1600 and the object is restricted to the ParentClass's methods and fields, it prints 1600.

An example would be as follows:

Consider I had an Apple Class and a Fruit class:

public class Fruit {
    private String type;

    public Fruit(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

And the Apple Class:

public class Apple extends Fruit {
     private String variant;

     public Apple(String variant) {
          System.out.println("I like " + variant + apples too!");
          super("Apple");
     }

     public String getVariant() {
          return variant;
     }
}

And now I instantiate like this:

Fruit ap = new Apple("Fiji");

I don't have access to getVariant() or any methods in the Apple class because the type is of the parent class, not of Apple. I would be able to do getType() but that's it.

In your case:

public class SportsCar extends Car {
    public int volume;

    SportsCar() {
        this(3000); 
    }

    SportsCar(int volume) { 
        this.volume = volume; 
    }

    public String toString() {
        return "SportsCar:"+volume;
    }
}

Although SportsCar has it's own constructor and takes it's own volume, the parent class Car is the actual type, causing the Car constructor to be called, hence setting volume to 1600. To specify a SportsCar object, do this:

SportsCar sc = new SportsCar(3500);
System.out.print(sc.toString());

This will print out:

SportsCar:3500

You can also typecast it like so:

Car c = new SportsCar(1600);
System.out.print(((SportsCar) c).toString());
Andrew Li
  • 55,805
  • 14
  • 125
  • 143
1

So the point here is that when you are using car.volume, car variable is of type Car and object reference is of type SportsCar.

As both the classes have the same element named volume and you are trying to refer it through parent object variable, it is returning 1600.

If you will typecast and then check the volume, it will return 3500 as per below code:

System.out.println(((SportsCar)car).volume);
Aman Chhabra
  • 3,824
  • 1
  • 23
  • 39
0

Aman Chhabra answer is right. You created a SportCar object which is from the Car "family". And what you are printing is the volume of Car, not the volume of SportCar.

One other way is to create a SportsCar object instead of Car.

P.s: you should always set your class attributes as private :)

nunoymr
  • 16
  • 3