发布
社区首页 >问答首页 >初始化子类中的超类变量(构造函数中需要)

初始化子类中的超类变量(构造函数中需要)
EN

Stack Overflow用户
提问于 2015-10-07 20:52:55
回答 6查看 3.9K关注 0票数 6

我正在编写一个简单的小行星克隆游戏,使用Swing显示图形。我有点喜欢德里克·巴纳斯的教程,但我决定自己扩展。

最初的想法是,游戏中的每一个图形元素(即小行星、飞船和子弹)都扩展了Polygon类。他们的构造函数看起来如下所示:

代码语言:javascript
代码运行次数:0
复制
public class SpaceShip extends Polygon {

    //x and y coordinates
    public static int[] polyXArray = {...};
    public static int[] polyYArray = {...};

    //other class variables
    {...}

    public SpaceShip() {

        super(polyXArray, polyYArray, polyXArray.length);
    }
}

其他图形元素也是一样的。

编辑:这里的关键元素是,这两个数组不存储对象的实际坐标,而是它们相对于中心的位置,其坐标是double-type类变量。因此,数组只描述对象的形状,而子类move()方法将影响中心的坐标。负责实际绘制的类将调用move()方法,然后应用仿射变换来移动和旋转形状(根据正确定义的角度参数)。我这样做是为了避免与处理double算法相关的精度问题。

现在,由于元素有许多“相等”变量(它们的中心坐标,为了用仿射变换将它们转换为中心坐标,它们的速度分量等等)和方法(getter和setter、move()方法等)我想让它们成为一个抽象类的扩展,比方说,GameShape,它包含了所有这些常见的方法和变量。现在,GameShape将直接扩展Polygon

代码语言:javascript
代码运行次数:0
复制
public abstract class GameShape extends Polygon {

        //x and y coordinates, still unassigned
        public static int[] polyXArray, polyYArray;

        //other class variables
        {...}

        public GameShape() {

            super(polyXArray, polyYArray, polyXArray.length);
        }
}

然后,当我定义不同的子类以绘制我需要的不同形状时,我想要将所需的值分配给polyXArraypolyYArray,但是我还没有找到一种方法。

我确实希望这些变量是静态的,因为它们是单个类的特定属性,而且我不希望每次实例化新对象时都将它们作为参数传递。

我的情况与这个问题中描述的情况非常相似,但建议的解决方案似乎不起作用,因为我需要构造函数中的那些变量。有什么办法可以克服这个问题吗?不管过程如何,我的主要目标是拥有一个与所有图形元素共同的超类,以避免数十行复制粘贴的代码。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2015-10-07 21:02:36

编辑:

正如VGR在评论中指出的那样,这将不会编译。因此,我们将不得不稍微修改实现,即我们将使用have关系而不是IS关系:)

首先,不要使聚数组字段静态。如果您这样做了,那么对于所有的子类来说,它们都是相同的,那么有什么意义呢?

其次,在这里使用模板方法设计模式。你的课会是这样的:

代码语言:javascript
代码运行次数:0
复制
public abstract class GameShape {

        //x and y coordinates, still unassigned
        public int[] polyXArray, polyYArray;

        private Polygon polygon;

        //other class variables
        {...}

        public GameShape() {
            instantiatePolyArrays();
            this.polygon = new Polygon(polyXArray, polyYArray, polyXArray.length);
        }

        protected abstract void instantiatePolyArrays();

        public final Polygon getPolygon(){
            return this.polygon;
        }
}

每个扩展类都必须重写此方法,并且可以为每个方法重写中的每个类实例化数组。

另外,还有一个关于is - with问题的词--在您的示例中,您展示的是一个IS关系,其中GameShape对象是一个Polygon,因此需要调用超级构造函数,并由此产生问题。在我的解决方案中,这被替换为一个HAS关系,其中GameShape对象内部有一个Polygon对象,并使用getPolygon()方法进行访问。这允许您有更多的灵活性:-)

票数 -1
EN

Stack Overflow用户

发布于 2015-10-07 21:05:53

您有一对数组,用于描述特定种类的游戏对象的形状。如果不同的游戏对象可以有不同的形状,那么它们都不能共享一个单独的数组,就像它们是所有游戏对象类的公共超类的静态属性一样。同一类型的不同对象可以共享相同的数组(假设这些数组不需要在每个对象的基础上进行修改),这可能对应于这些数组是具体游戏对象类的静态字段。但是,在这种情况下,如果您希望这些类的超类能够访问给定游戏对象的正确形状数据,那么必须告诉它这些形状数据是什么。

有两种主要的方法可以做到这一点:

  1. 可以将适当的形状数组传递给超类的构造函数。你说你不想这么做,但我不明白为什么。
  2. 您可以在子类应该覆盖的超类上定义访问器方法,以提供正确的形状数据(这称为模板方法模式)。
票数 2
EN

Stack Overflow用户

发布于 2015-10-07 21:08:26

数组字段不能是static,因为不同形状的坐标不同。另外,在特定的子类中不需要这些数组,因为它们已经在PolygonGameShape中了。

下面是我编写GameShape的方式(虽然我同意@Michael,您不需要同时将polyXArraypolyXArray.length传递给构造函数)。

代码语言:javascript
代码运行次数:0
复制
public abstract class GameShape extends Polygon {

    // I got rid of the array fields as I think they are in Polygon anyway.

    //other class variables
    {...}

    // I added arguments to your constructor.
    public GameShape(int[] polyXArray, int[] polyYArray) {

        super(polyXArray, polyYArray, polyXArray.length);
    }
}

问题是super必须是构造函数的第一行,但是可以使用私有方法来构建数组:

代码语言:javascript
代码运行次数:0
复制
public final class BoringRectangle extends GameShape {

    public BoringRectangle(int left, int right, int top, int bottom) {
        super(xArray(left, right), yArray(top, bottom));
    }

    private static int[] xArray(int left, int right) {
        return new int[] {left, right, right, left};
    }

    private static int[] yArray(int top, int bottom) {
        return new int[] {bottom, bottom, top, top};
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33002225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档