Java- 静态变量,但扩展子类不共享该值
Java- variable that's static, but extended subclasses don't share the value
假设我有一个 class:
public abstract class Foo{
public static int i = 0;
}
我想这样做,当我有 2 个额外的 class 时,像这样:
public class Bar extends Foo{
public Bar(){ i=1; }
}
和
public class t extends Foo{
public t(){ i=-1;}
}
Bar.i 和 t.i 不是相同的值,而是相对于它们各自的子 class 是静态的。
这是如何正确完成的?
这是一个更好的例子:
说我有一个 class:
public abstract class vehicle{
public static int tires;
}
我有两个子 classes:
public class car extends vehicle{
public car(){
//ALL cars have 4 tires. this is static to cars.
tires = 4;
}
}
和
public class motorcycle extends vehicle{
public motorcycle(){
//All motorcycles have 2 tires. this is static to motorcycles.
tires = 2;
}
}
显然,汽车和摩托车 NOT 具有相同数量的轮胎,但我仍然希望能够访问 car.tires 和 motorcycle.tires ,分别返回 4 和 2。鉴于变量是车辆,我还希望能够调用 {variableName}.tires。我也希望以后能够像这样添加更多变量,例如另一个 int numberOfLights
.
这是你应该做的吗?我不太确定你在问什么。
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;
}
不过,他们确实分享了价值。 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);
要么您想要每个 class 中的变量,要么您实际上想要实例变量,而不是 class 变量。
更新
至于你的更好的例子,你需要抽象方法,而不是静态变量。
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; }
}
你不能为所欲为,static 不做虚拟查找。当您调用严格引用 Vehicle 上的 class 变量的 Vehicle.tires
时,它不会查看 subclass 中的任何内容。
对于在 class 上引用静态变量的代码,它必须首先查找您在表达式中指定的特定 class,然后向上查找 class 层次结构(朝向根,java.lang.Object),直到找到匹配项。因此,如果您调用 Motorcycle.tires
而 Motorcycle 没有名为 tires 的静态变量,JVM 将在 Vehicle 上找到该名称的变量,但是如果您调用 Vehicle.tires
则它不会找到变量摩托车上的那个名字。
这与虚拟查找相反,在虚拟查找中,您的代码甚至可能不知道它正在处理什么子class,它让对象在运行时计算出动态触发的行为。要使用静态变量和方法,调用它们的代码必须在编译时非常具体地说明它使用的是什么 subclass 。这就是他们称之为静态的原因,因为它不会改变。
这里最好避免使用static。您可以拥有 Vehicle 将委托给的某种通用组件,以获取轮胎数量:
public Vehicle {
private VehicleConfig config;
public int getTireCount() {
return config.getTireCount();
}
}
将配置放在一个单独的对象中意味着您可以从包含它的事物中单独管理它的范围。使用静态同样是一种管理对象范围的尝试,只是以一种不灵活的方式。
假设我有一个 class:
public abstract class Foo{
public static int i = 0;
}
我想这样做,当我有 2 个额外的 class 时,像这样:
public class Bar extends Foo{
public Bar(){ i=1; }
}
和
public class t extends Foo{
public t(){ i=-1;}
}
Bar.i 和 t.i 不是相同的值,而是相对于它们各自的子 class 是静态的。
这是如何正确完成的?
这是一个更好的例子:
说我有一个 class:
public abstract class vehicle{
public static int tires;
}
我有两个子 classes:
public class car extends vehicle{
public car(){
//ALL cars have 4 tires. this is static to cars.
tires = 4;
}
}
和
public class motorcycle extends vehicle{
public motorcycle(){
//All motorcycles have 2 tires. this is static to motorcycles.
tires = 2;
}
}
显然,汽车和摩托车 NOT 具有相同数量的轮胎,但我仍然希望能够访问 car.tires 和 motorcycle.tires ,分别返回 4 和 2。鉴于变量是车辆,我还希望能够调用 {variableName}.tires。我也希望以后能够像这样添加更多变量,例如另一个 int numberOfLights
.
这是你应该做的吗?我不太确定你在问什么。
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;
}
不过,他们确实分享了价值。 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);
要么您想要每个 class 中的变量,要么您实际上想要实例变量,而不是 class 变量。
更新
至于你的更好的例子,你需要抽象方法,而不是静态变量。
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; }
}
你不能为所欲为,static 不做虚拟查找。当您调用严格引用 Vehicle 上的 class 变量的 Vehicle.tires
时,它不会查看 subclass 中的任何内容。
对于在 class 上引用静态变量的代码,它必须首先查找您在表达式中指定的特定 class,然后向上查找 class 层次结构(朝向根,java.lang.Object),直到找到匹配项。因此,如果您调用 Motorcycle.tires
而 Motorcycle 没有名为 tires 的静态变量,JVM 将在 Vehicle 上找到该名称的变量,但是如果您调用 Vehicle.tires
则它不会找到变量摩托车上的那个名字。
这与虚拟查找相反,在虚拟查找中,您的代码甚至可能不知道它正在处理什么子class,它让对象在运行时计算出动态触发的行为。要使用静态变量和方法,调用它们的代码必须在编译时非常具体地说明它使用的是什么 subclass 。这就是他们称之为静态的原因,因为它不会改变。
这里最好避免使用static。您可以拥有 Vehicle 将委托给的某种通用组件,以获取轮胎数量:
public Vehicle {
private VehicleConfig config;
public int getTireCount() {
return config.getTireCount();
}
}
将配置放在一个单独的对象中意味着您可以从包含它的事物中单独管理它的范围。使用静态同样是一种管理对象范围的尝试,只是以一种不灵活的方式。