【问题标题】:How do I use a subclass' static fields in superclass' method when calling via instance of subclass?通过子类的实例调用时,如何在超类方法中使用子类的静态字段?
【发布时间】:2019-01-29 18:49:32
【问题描述】:

我有一个模型类,有一个名为 square 的子类。在模型类中,我有一个 draw 方法,它需要子类中的一些字段。我有一个子类的实例,并想调用它的绘制函数(在子类中不会被覆盖)。

我正在尝试在 Android 上使用 openGL 制作一些东西,并且有很多模型使用基本相同的代码进行绘制,但使用不同的网格,因此具有不同的字段。我认为将绘制函数复制到每个模型类有点多余,当我尝试在模型类上简单地添加空字段并在子类上添加同名字段时,它在调用时使用超类中的字段使用子类实例的方法,此外,将字段作为参数传递不是一种选择,因为超级构造函数调用必须是子类构造函数中的第一个调用,我需要对子类中的字段应用一些操作' 构造函数(我想,正如你所说,我对 OOP 没有经验)。

以下很多内容都是暂时的,因为我仍在努力掌握事情的窍门

精简模型超类:

abstract public class Model {
    static final int COORDS_PER_VERTEX = 3;
    final float Coords[];
    public Model(){
        //do some stuff unrelated to the issue
        }
    public void draw(){
        final int vertexCount = Coords.length / COORDS_PER_VERTEX;
        }
    }

精简模型子类:

public class Square extends Model{
    private static float Coords[] = {
                -0.5f, 0.5f, 0.0f,   // top left
                -0.5f, -0.5f, 0.0f,   // bottom left
                0.5f, -0.5f, 0.0f,   // bottom right
                0.5f,  0.5f, 0.0f }; // top right
    public Square() {
        super();
        //do something to Coords
        }
    }

方法调用:

private ArrayList<Model> models = new ArrayList<>();
models.add(new Square());
for (Model model:models) {
        model.draw();
    }

我希望 draw 函数将 12/3=4 用于 vertexCount,但它会引发 NullPointer 错误,因为您不能在空数组上使用 .length

【问题讨论】:

  • 但是draw 在不同的形状上会有所不同,对吧?这不是多余的。也可以在构造函数之外使用super()
  • 它不会对不同的形状做不同的事情 - 它总是绘制网格中的每个三角形。
  • 它们有什么不同吗? Vertex Buffer Object在显卡上存储顶点,会比每次上传到GPU都要快。
  • 我实际上确实使用了顶点缓冲区,这是我试图传递的字段之一。就像我在帖子中提到的那样,我发布的代码被精简到最低限度以重新创建问题,正如堆栈溢出所建议的那样。

标签: java oop


【解决方案1】:

因为继承不适用于字段。 你的代码应该是这样的

abstract public class Model {
    static final int COORDS_PER_VERTEX = 3;
    public Model(){
        //do some stuff unrelated to the issue
    }
    public void draw(){
        final int vertexCount = getCoords().length / COORDS_PER_VERTEX;
    }
    abstract public float[] getCoords();
}

public class Square extends Model {
    private static float Coords[] = {
                -0.5f, 0.5f, 0.0f,   // top left
                -0.5f, -0.5f, 0.0f,   // bottom left
                0.5f, -0.5f, 0.0f,   // bottom right
                0.5f,  0.5f, 0.0f }; // top right
    public Square() {
        super();
        //do something to Coords
    }

    public float[] getCoords() {
        return Coords;
    }
}

abstract public class Model {
    static final int COORDS_PER_VERTEX = 3;
    protected float coords[];

    public Model(float[] coords){
        this.coords = coords;

        //do some stuff unrelated to the issue
    }
    public void draw(){
        final int vertexCount = coords.length / COORDS_PER_VERTEX;
    }
}

public class Square extends Model {
    public Square(){
        super(new float[] {
            -0.5f, 0.5f, 0.0f, 
            -0.5f, -0.5f, 0.0f,
            0.5f, -0.5f, 0.0f, 
            0.5f,  0.5f, 0.0f }
        );
    }
}

【讨论】:

  • 非常直观,继承不适用于字段。我仍然必须将相同的函数(在本例中为 getCoords())复制到每个子类,这有点烦人,真的没有办法不必将相同的函数复制到每个子类吗?
  • 第二个选项不起作用,因为我需要能够在初始化后更改坐标,以及在初始化之前对坐标做一些事情。还是谢谢!
  • 这只是一个例子。当然,您可以在抽象类中添加 setter,稍后以相同的方式设置数组。
【解决方案2】:

您可以编写一个返回Coords 数组的getter 方法。这样每个子类都可以覆盖它以返回不同的变量。

abstract public class Model
{

    protected float[] getCoords() {
        return Coords;
    }

}

public class Square extends Model {

    @Override
    protected float[] getCoords() {
        return Coords;
    }

}

我知道在实例方法中返回static 实例变量没有多大意义,但您只能覆盖实例方法。

【讨论】:

  • 这感觉就像在每个类中复制draw方法一样多余,但如果真的没有办法直接使用变量,我会求助于这个。
猜你喜欢
  • 1970-01-01
  • 2012-12-19
  • 2012-12-30
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多