如何使用“ class”作为Map的键?

时间:2019-10-21 01:12:36

标签: dart

我使用Piece class作为Map的密钥。

但是运行此代码后,发生了错误Uncaught exception: C.JSNull_methods.$indexSet is not a function

class Piece {
  int type;

  Piece(this.type);
}

void main() {
  Map<Piece, int> hand;
  hand[Piece(5)] = 5;

  if (hand.containsKey(Piece(5))) {
    print("contains");
  }

  print('${hand[Piece(5)]}');
}

在dart-lang中,如何使用class作为Map的键?

1 个答案:

答案 0 :(得分:0)

首先,您遇到的错误与将类型用作键无关,但是在您从未初始化hand变量之前就已发生。因此,您需要这样做:

Map<Piece, int> hand = {};

现在,您将不会收到异常,但是您的代码将无法正常工作,因为hand.containsKey(Piece(5))将返回false,而print('${hand[Piece(5)]}')将返回null

这是因为映射Map<Piece, int>没有使用Type作为键,而是使用了Piece类型的对象。因此,如果我们将您的代码放在这里:

  Map<Piece, int> hand = {};
  hand[Piece(5)] = 5;

  if (hand.containsKey(Piece(5))) {
    print("contains");
  }

  print('${hand[Piece(5)]}');

您在这里创建一个新的Piece类型的对象实例,每种类型您正在编写“ Piece(5)”。由于每个对象都是片断的单独实例,因此您将不会收到保存的值5,因为为与请求不同的对象保存了值5。

有多种解决方案,我不知道哪一种最适合您。但是在这种情况下,简单的解决方案是只创建一个Piece实例并重用该实例:

void main() {
  Map<Piece, int> hand = {};
  final piece = Piece(5);
  hand[piece] = 5;

  if (hand.containsKey(piece)) {
    print("contains");
  }

  print('${hand[piece]}');
}

或者为Piece类创建一个const构造函数,以便将具有相同参数的实例放入同一对象。此解决方案要求int type是最终的,因为您不能编辑const构造的对象(因为它是常量):

class Piece {
  final int type;

  const Piece(this.type);
}

void main() {
  Map<Piece, int> hand = {};
  hand[const Piece(5)] = 5;

  if (hand.containsKey(const Piece(5))) {
    print("contains");
  }

  print('${hand[const Piece(5)]}');
}

请注意,每当您需要确保实例将为相同的参数返回相同的对象时,都需要在对象实例化前加上const,例如“ const Piece(5)”。