【问题标题】:Modifying parent classes variables修改父类变量
【发布时间】:2017-03-05 14:56:46
【问题描述】:

我在网上四处寻找解决此问题的方法,但无法解决。

我想扩展精灵类来制作我自己的互动圈。一切正常,但设置自定义类的 X、Y、宽度和高度不起作用:

class CircleDraw extends Sprite
{

public function new(x:Int,y:Int,width:Int,height:Int)
{
    super();
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    drawCircle();
}

private function drawCircle()
{
    this.graphics.beginFill(0xffffff);
    this.graphics.drawCircle(this.x,this.y, this.width);
    this.graphics.endFill();
}
}

上面的方法没有按预期工作,通过构造函数设置 x,y 和宽度实际上什么都没有出现。然而,如果我手动设置它们,无论是在课堂上

this.graphics.drawCircle(200,200, 30);

或在 addChild 之前:

 circle = new CircleDraw(10,10,100,200);
 circle.x=100;
 circle.y=100;

然后它出现在屏幕上。一旦在类中手动添加值而不是 this.x 等,也可以像这样添加它:

circle = new CircleDraw(10,10,100,200);
addChild(circle);

所以我的问题是,我如何扩展一个类(Sprite)并允许构造函数修改其父级默认变量并保留值?

编辑

只是按要求提供所有代码:

这不起作用:

    circle = new CircleDraw(10,10,100,200);
    addChild(circle);

当画圆时是这样的:

class CircleDraw extends Sprite
{
    public function new(x:Int,y:Int,width:Int,height:Int)
    {
        super();
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
        drawCircle();
    }

    private function drawCircle()
    {
        this.graphics.beginFill(0xffffff);
        this.graphics.drawCircle(this.x, this.y, this.width);
        this.graphics.endFill();
    }

}

如果我修改方法,它确实有效:

private function drawCircle()
        {
            this.graphics.beginFill(0xffffff);
            this.graphics.drawCircle(200, 200, 30);
            this.graphics.endFill();
        }

或者,如果在对象的实例化过程中,我设置了编辑前提到的 X 和 Y 变量。

【问题讨论】:

    标签: haxe openfl


    【解决方案1】:

    您确实成功地设置了基类变量,只是DisplayObject.width 有一个相当具体的(也许不是那么明显)的行为。

    width:Float

    表示显示对象的宽度,以像素为单位。宽度是根据显示对象内容的边界计算的。当你设置width属性时,scaleX属性也会相应调整,如下代码所示:

    除了 TextField 和 Video 对象外,没有内容的显示对象(例如空精灵)的宽度为 0,即使您尝试将 width 设置为不同的值。
    ——OpenFL API: DisplayObject: width

    从这个意义上说,OpenFL 遵循ActionScript 3.0 API

    【讨论】:

    • 这意味着您不能手动设置宽度值。换句话说,OP 正在绘制一个半径为零的圆。这应该是正确的答案。
    【解决方案2】:

    据我推测,您似乎正在尝试覆盖不带参数的构造函数(新的)。

    我不完全确定,但这可能无法满足您的需求。我认为您实际上在做的只是在扩展类上创建一个“新”方法,然后在其中不为父级提供任何内容(super())。所以父级不会有构造函数参数。在调试器中查看该对象并查看实例属性与父属性会很有趣。

    可能有一种解决方法,但我认为您可能希望通过组合而不是继承来实现这一点。例如,在“new”中,创建一个精灵的新实例,并操纵它的属性。

    class MySprite
    {
        public var sprite : Sprite;
    
        public function new ( ) {
            sprite = new Sprite ();
        }
    }
    

    然后您将在该精灵实例上执行您的操作。本质上,您只是在自己的类中包装了一个精灵。装饰师,或多或少。

    我在这里找到了对该主题的一些参考(我已经有一段时间没有进行任何 Flash 编程了),它显示了 addChild 和 removeChild 实现等。

    http://old.haxe.org/forum/thread/685

    【讨论】:

    • 这似乎是一种有趣的方式,但如果我使用精灵实例,我是否必须使用 getter 方法将精灵作为对象返回以添加到屏幕?我想扩展原来的 sprite 类,如果有意义的话我可以直接 addChild(MySprite)
    • 嗯,看看那篇文章。您只需为您的 sprite 包装器创建 addChild 实现。我知道你想要做的是或多或少地像处理精灵类一样处理这个类。一个让步可能是,您必须执行 MySprite.getSprite 或类似的操作。否则,您只需镜像 sprite 的 API 并获得您想要的。我记得过去处理过这样的事情,我最终认为,作为一项规则,最好通过组合来处理这些事情。
    • 谢谢,这实际上很好地解释了问题。起初似乎很奇怪,尽管无法以您期望的方式处理它,但由于平台限制是有道理的....仍然很不方便,因为 id 花了一些时间,所以盒子上没有警告假设这是一个编程逻辑问题,试图在没有组合的情况下解决这个问题。感谢您的提示!
    • 不,这个“解决方案”没有回答 OP。正如我所说,OP 分配像 应该 这样的变量的方式。一定是某处发生了一些事情,使其无法按预期运行。
    • 我不否认“有效”的解决方法。我只是认为,充分了解根本原因更重要,并且几乎总是会导致更优化的解决方案。在这种情况下,分配一个额外的对象作为包装器并不是最优的,因为它使用更多的内存、cpu 等。相比之下,知道根本原因(比如你不能设置精灵的宽度)并简单地使用指定圆圈大小的其他方法可以让您免于额外开销。
    【解决方案3】:

    从您发布的(部分)代码来看,它应该可以工作。

    换句话说,像这样设置父级的变量应该可以工作。

    我怀疑您没有发布的其他代码会妨碍您。我建议您在 drawCircle 调用中打印出 x、y 值以进行调试。

    我也怀疑圆圈是在屏幕外绘制的,所以你看不到它。因为您首先将精灵移动到 (x,y),然后在精灵内部的 (x,y) 中绘制一个圆圈。因此,圆在全局空间中有效地位于 (2x,2y)

    编辑:

    this.graphics.drawCircle(200,200, 30);
    

    您声称这有效。应该在 (210,210) 处绘制,半径为 30

    circle = new CircleDraw(10,10,100,200);
    circle.x=100;
    circle.y=100;
    

    您声称这有效。应该在 (200,200) 处绘制,半径为 100

    circle = new CircleDraw(10,10,100,200);
    addChild(circle);
    

    您声称这不起作用。应该在 (20,20) 处绘制,半径为 100

    从上面的三个版本中,你实际上是在不同的地方用不同的尺寸画图。所以我仍然怀疑“没有工作”可能是因为你在一些看不见的地方画画。

    所以我还是建议你在私有 drawCircle 函数中打印出 x、y、width 的值,看看发生了什么

    【讨论】:

      【解决方案4】:

      请注意,您是在处理 2 个坐标空间。一个是将添加 Sprite 和该 Sprite 的图形对象。如果你设置了this.xthis.width,你实际上是在设置这个Sprite 的属性。因此,在这种情况下,就定位而言,您正在移动 Sprite 本身。 Sprite 的“图形”属性有它自己的坐标空间。

      例如,如果您在 CircleDraw 构造函数中传递 x=100,您首先将精灵本身移动 x=100,然后绘制 x 偏移为 100 的圆。因此,如果您要将精灵直接添加到舞台你实际上会在x=200 开始画你的圆圈,因为你有效地应用了这个位置两次。在我看来,这并不是你真正想要的。

      当你构建它时,你的 CircleDraw 实例(当然也是一个 Sprite)是“空的”。所以在你的构造函数中调用this.width = width 没有任何效果。 this.width 将保持为 0,因为此时 Sprite 没有内容。因此,在 drawCircle 方法中,您正在绘制一个 width 为 0 的圆。

      可能更好的解决方案是简单地将构造函数的参数传递给 drawCircle 函数,而不设置任何属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-02
        • 1970-01-01
        • 2012-02-06
        • 2013-04-15
        • 2015-04-15
        • 2016-04-17
        • 1970-01-01
        • 2017-07-11
        相关资源
        最近更新 更多