dart中有类似结构体的东西吗?

gg58donl  于 2023-02-14  发布在  其他
关注(0)|答案(6)|浏览(200)

在javascript中,人们总是把对象当作向量来使用,比如{x: 1, y: 2},而不是使用数组[1,2]。数组的访问时间比对象快得多,但是通过索引访问更容易混淆,特别是当你需要一个大数组的时候。我知道dart有固定的数组,但是有没有办法像你在另一种语言中命名一个结构体或者元组/记录那样命名数组的偏移量?定义枚举/常量?
我想要的是

List<int> myVector = new List([x,y]);
myVector.x = 5;

有没有一种等效或惯用的方法来做到这一点?

dojqjjoe

dojqjjoe1#

听起来像是一堂课。

class MyVector {
   int x;
   int y;
   MyVector(this.x, this.y);
 }

在运行时创建名称索引结构没有更简单和更有效的方法,为了简单起见,通常可以使用Map,但它不如真实的的类有效。
一个类至少应该和一个定长列表一样高效(时间和内存),毕竟它不需要做索引边界检查。
在Dart 3.0中,该语言将引入记录。此时,您可以使用带有命名字段的记录,而不是创建一个原语类:

var myVector = (x: 42, y: 37);
print(myVector.x);

记录是不可修改的,因此在创建记录后,您将无法更新值。

2o7dmzc5

2o7dmzc52#

对我来说,我认为有两种方法可以做到这一点。我将按我的观点最好的排序

    • 基于类的方法**

这里的方法是将您的需求封装在一个专用对象中

  • 优点:*
  • 它被封装了
  • 你可以根据需要提出几种访问变量的方法
  • 您可以扩展功能而不破坏一切
  • 我喜欢它:p
  • 缺点 *
  • 花更多时间创建类等。
  • 你真的需要我说的专业术语吗?
  • 也许对js的人来说很奇怪
    示例:
class Vector {
  int x;
  int y;

  static final String X = "x";
  static final String Y = "y";

  Vector({this.x, this.y});
  Vector.fromList(List<int> listOfCoor) {
    this.x = listOfCoor[0];
    this.y = listOfCoor[1];
  }

  // Here i use String, but you can use [int] an redefine static final member
  int operator[](String coor) {
    if (coor == "x") {
      return this.x;
    } else if (coor == "y") {
      return this.y;
    } else {
      // Need to be change by a more adapt exception :)
      throw new Exception("Wrong coor");
    }
  }
}

void main() {
  Vector v = new Vector(x: 5, y: 42);
  Vector v2 = new Vector.fromList([12, 24]);

  print(v.x); // print 5
  print(v["y"]); // print 42
  print(v2.x); // print 12
  print(v2[Vector.Y]); // print 24
}
    • 基于枚举的方法:**

您还可以定义一个"枚举"(实际上并没有真正实现,但将在未来版本中实现),它将包含指向您的值的"快捷方式

  • 优点 *
  • 更易于实施
  • 更像是你的例子;p
  • 缺点 *
  • 可扩展性较差
  • 我觉得不是很漂亮
  • 不是OOP思维
  • 示例:*
class Vector {
  static final int x = 0;
  static final int y = 1;
}

void main() {
  List<int> myVector = new List(2);
  myVector[Vector.x] = 5;
  myVector[Vector.y] = 42;
}

做出选择;p

igetnqfo

igetnqfo4#

如果你有相当大的数据结构,你可以使用"dart:typed_data"作为模型,并为存储的数据提供轻量级视图。这样的话,开销应该是最小的。例如,如果你需要Uint8值的4X4矩阵:

import "dart:typed_data";
import "dart:collection";
import "package:range/range.dart";
class Model4X4Uint8 {
  final Uint8List _data;
  static const int objectLength = 4 * 4;
  final Queue<int> _freeSlotIndexes;
  Model4X4Uint8(int length): _data = new Uint8List((length) * objectLength),
        _freeSlotIndexes = new Queue<int>.from(range(0, length));
  int get slotsLeft => _freeSlotIndexes.length;
  num operator [](int index) => _data[index];
  operator []=(int index, int val) => _data[index] = val;
  int reserveSlot() =>
      slotsLeft > 0 ? _freeSlotIndexes.removeFirst() : throw ("full");
  void delete(int index) => _freeSlotIndexes.addFirst(index);
}
class Matrix4X4Uint8 {
  final int offset;
  final Model4X4Uint8 model;
  const Matrix4X4Uint8(this.model, this.offset);
  num operator [](int index) => model[offset + index];
  operator []=(int index, int val) => model[offset + index] = val;
  void delete() => model.delete(offset);
}
void main() {
  final Model4X4Uint8 data = new Model4X4Uint8(100);
  final Matrix4X4Uint8 mat = new Matrix4X4Uint8(data, data.reserveSlot())
      ..[14] = 10
      ..[12] = 256; //overlow;
  print("${mat[0]} ${mat[4]} ${mat[8]} ${mat[12]} \n"
        "${mat[1]} ${mat[5]} ${mat[9]} ${mat[13]} \n"
        "${mat[2]} ${mat[6]} ${mat[10]} ${mat[14]} \n"
        "${mat[3]} ${mat[7]} ${mat[11]} ${mat[15]} \n");
  mat.delete();
}

但这是一个非常低级的解决方案,很容易在内存管理和溢出方面产生一些隐蔽的错误。

bvpmtnay

bvpmtnay5#

您还可以在List上使用extension来创建特定索引的别名。
虽然设置互斥别名很困难,但在某些情况下,这可能是一个简单的解决方案。

import 'package:test/test.dart';

extension Coordinates<V> on List<V> {
  V get x => this[0];

  V get y => this[1];

  V get z => this[2];
}

void main() {
  test('access by property', () {
    var position = [5, 4, -2];
    expect(position.x, 5);
    expect(position.y, 4);
    expect(position.z, -2);
  });
}
oyxsuwqo

oyxsuwqo6#

元组包https://pub.dev/packages/tuple可能是您在类太重时要查找的包。

import 'package:tuple/tuple.dart';

const point = Tuple2<int, int>(1, 2);

print(point.item1); // print 1
print(point.item2); // print 2

相关问题