这个使用Streams的代码是错误的还是我应该提交错误?

时间:2013-04-01 07:19:15

标签: dart

我写的代码对于一个问题可能有点长,但是,我想知道是否有错误,所以我可以将它提交给dartbug.com。如果没有错误,我想知道我做错了什么。

代码的想法是将点的位置与网格同步(分别为Square类和Grid类)。

Square.onPosChange是一个发送先前位置的Stream。

当一个正方形被添加到Grid(Grid.add)时,会有一个对onPosChange的订阅,它所做的就是改变Grid中正方形的位置;首先它将它从前一个位置移除(只是指定null),然后将其分配给当前位置。

当我预期前一个位置为空时,我的测试失败了。现在下面是代码并注意我认为可能是问题的注释行。

编辑:以防万一,这不是愚人节问题:P

import 'dart:async';
import 'package:unittest/unittest.dart';

void main() {
  test('grid',(){
    Square s = new Square(3, 5);
    Grid g = new Grid(10,10);
    g.add(s);
    expect(g._cols[3].squares[5], s);//pass
    s.x = 6;
    expect(g._cols[6].squares[5], s);//pass
    expect(g._cols[3].squares[5], isNull);//fails

  });
}

class Grid{
  List<GridCol> _cols;
  int w, h;
  Grid(this.w, this.h){
    _cols = new List<GridCol>.filled(w, new GridCol(h));
  }
  add(Square square){
    if(!isOut(square)){
      //add square to grid
      _cols[square.x].squares[square.y] = square;
      //listen to onPosChanged event stream
      square.onPosChanged.listen((Point previousPos){
        //remove from previous position
        _cols[previousPos.x].squares[previousPos.y] = null;
        //if is not out of bounds, add in new position
        if(!isOut(square)){
          /*
           * Up until this point, (3,5) is null, as was set earlier.
           * (6,5) is also null since it was never set.
           * 
           * But after the following line, strangely,
           *  both (3,5) and (6,5) are set to the square.
           */
          _cols[square.x].squares[square.y] = square;

          print("(3,5): ${_cols[3].squares[5]}");//(3,5): (6,5)
          print("(6,5): ${_cols[6].squares[5]}");//(6,5): (6,5)
        }

      });
    }
  }

  isOut(Point p) => 
      p.x < 0 || p.y < 0 || p.x >= w || p.y >= h;
}

class GridCol{
  List<Square> squares;
  GridCol(int h): squares = new List<Square>(h);
}

class Square extends Point{
  int get x => super.x;
      set x (value){
        var prev = super.x;
        super.x = value;
        _sc.add(p(prev, y));
      }
  int get y => super.y;
      set y (value){
        var prev = super.y;
        super.y = value;
       _sc.add(p(x,prev));
      }

  StreamController<Point> _sc;
  Stream get onPosChanged => _sc.stream;
  Square(x, y)
  {
    super.x = x;
    super.y = y;
    _sc = new StreamController<Point>.broadcast();
  }
}

 class Point{
    int x = 0;
    int y = 0; 
    Point([this.x, this.y]);
    String toString() => '($x,$y)';
}

p(x, y) => new Point(x, y);

1 个答案:

答案 0 :(得分:6)

这是一个难以追踪的问题,但这是你的修复,它与Streams无关。

Grid的构造函数如下所示:

Grid(this.w, this.h){ 
  _cols = new List<GridCol>.filled(w, new GridCol(h));
}

您希望_cols中的每个元素都填充new GridCol(h);。实际上你得到的(以及代码实际上说的内容)是用GridCol的相同实例填充每个元素。重写时可以更好地看到:

Grid(this.w, this.h){
  var gridCol = new GridCol(h);  // create a single instance of a GridCol
  _cols = new List<GridCol>.filled(w, gridCol); // add that instance to every element
}

这意味着当您添加第一个方块时,每个GridCol都是相同的单个实例,最终会得到一个看起来像这样的网格(-为空且S是你的方块):

---S------
---S------
---S------
---S------
---S------
---S------
---S------
---S------
---S------
---S------  

这恰好发生在add函数的开头,在涉及任何流之前,就在评论之后://add square to grid

如果使用以下代码初始化网格中的每个元素,则测试将通过。

Grid(this.w, this.h){
  _cols = new List<GridCol>(w); // create the list
  // fill each element with a different GridCol
  for (int i = 0; i < _cols.length; i++) {
   _cols[i] = new GridCol(h); // insert a new GridCol for every element.
  }
}