1

Let's say I have a class:

public abstract class Foo{
  public static int i = 0;
}

I want to make it so that when I have 2 additional classes like so:

public class Bar extends Foo{
   public Bar(){ i=1; }
}  

and

public class t extends Foo{
   public t(){ i=-1;}
}

that Bar.i, and t.i are not the same value, but rather static to their respective sub classes.

how is this done properly?

Here is a better example:

say I have a class:

public abstract class vehicle{
  public static int tires;
}

and I have two sub classes:

public class car extends vehicle{
  public car(){
    //ALL cars have 4 tires. this is static to cars.
    tires = 4;
  }
}

and

public class motorcycle extends vehicle{
  public motorcycle(){
    //All motorcycles have 2 tires. this is static to motorcycles.
    tires = 2;
  }
}

Obviously, cars and motorcycles do NOT have the same number of Tires, yet I still want to be able to access both car.tires and motorcycle.tires, returning 4 and 2 respectively. I would also like to have the ability to call {variableName}.tires, given that the variable is a vehicle. I would also like to have the ability to add more variables like this later, an example being another int numberOfLights.

3 Answers3

2

They do share the value, though. Example

// All print 0
System.out.println(Foo.i);
System.out.println(Bar.i);
System.out.println(T.i);

new Bar(); // all print 1
System.out.println(Foo.i);
System.out.println(Bar.i);
System.out.println(T.i);

new T(); // all now print -1
System.out.println(Foo.i);
System.out.println(Bar.i);
System.out.println(T.i);

Either you want a variable in each class, or you actually want instance variables, not class variables.

UPDATE

As for your better example, you want abstract methods, not static variables.

abstract class Vehicle {
    public abstract int getTires();
}

class Car extends Vehicle {
    @Override
    public int getTires() { return 4; }
}

class Motocycle extends Vehicle {
    @Override
    public int getTires() { return 2; }
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
1

Is this what you should be doing? I am not completely sure what you are asking.

public abstract class Foo{

}    

public class Bar extends Foo{
   public static int i = 0;
}  
and

public class t extends Foo{
   public static int i = 0;
}
SedJ601
  • 12,173
  • 3
  • 41
  • 59
0

You can't do what you want, static doesn't do virtual lookups. When you call Vehicle.tires that strictly references the class variable on Vehicle, it doesn't look at anything in the subclasses.

For code to reference a static variable on a class it has to start by looking on the specific class that you name in the expression, then working its way up the class hierarchy (toward the root, java.lang.Object) until it finds a match. So if you call Motorcycle.tires and Motorcycle doesn't have a static variable named tires, the JVM will find the variable of that name on Vehicle, but if you call Vehicle.tires then it won't find a variable of that name on Motorcycle.

This is the opposite of virtual lookups, where your code might not even know what subclass it's dealing with, it lets the object work out what behavior is triggered dynamically, at runtime. To use static variables and methods the code calling them has to be very specific about what subclass it's using, at compile time. That's why they call it static, because it doesn't change.

It would be better here to avoid using static. You could have some sort of common component that the Vehicle would delegate to in order to get the count of tires:

public Vehicle {
    private VehicleConfig config;
    public int getTireCount() {
        return config.getTireCount();
    }
}

Having the config be in a separate object means you can manage its scope separately from the thing containing it. Using static is likewise an attempt to manage objects' scope, just in an inflexible kind of way.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276