如何在Dart中使用变量泛型?

huangapple go评论63阅读模式
英文:

How to use variable generics in Dart?

问题

I'm learning dart and flutter, and looked at the Either functionality, but to use it you have to use Left and Right classes nad kinda look not so elegant.

我正在学习Dart和Flutter,看了一下Either功能,但要使用它,您必须使用Left和Right类,看起来不太优雅。

I'm trying to mplement my own OneOf class and it works:

我正在尝试实现自己的OneOf类,它可以工作:

class OneOf<T1, T2> {
  T1? _result1;
  T2? _result2;

  OneOf.formResult(dynamic result) {
    if (result is T1) {
      _result1 = result;
    } else if (result is T2) {
      _result2 = result;
    }
  }

  handle(
      {required void Function(T1?) handleT1,
      required void Function(T2?) handleT2}) {
    if (_result1 != null) {
      handleT1(_result1);
    } else if (_result2 != null) {
      handleT2(_result2);
    }
  }
}

as you can see the implementation uses two generic types, and you can handle the results with the handle function, now I want to have the three generics implementation, but Dart don't allow to have a class with the same name even when they handle a different number of generic parameters (I come from c# and there it is allowed).

正如您所看到的,该实现使用了两种泛型类型,并且您可以使用handle函数处理结果,现在我想要有三个泛型参数的实现,但是Dart不允许在处理不同数量的泛型参数时使用相同的类名(我来自C#,在那里是允许的)。

is there a way to have a variable amount of generic arguments in the class? or is there another solutin that I'm not seeeing for being new in the language?

是否有一种方法可以在类中具有可变数量的泛型参数?或者是否有其他解决方法,我还不清楚因为我对这门语言还不太熟悉?

for the curious the usage of this class would look like this

对于好奇的人,使用这个类的示例如下:

var message = "Hello world!!";
var result = OneOf<bool, String>.formResult(message);

result.handle(
  handleT1: (boolResult) {
    print("I have received a boolean");
  },
  handleT2: (stringResult) {
    print("I have received the string '$message'");
  },
);
英文:

I'm learning dart and flutter, and looked at the Either functionality, but to use it you have to use Left and Right classes nad kinda look not so elegant.

I'm trying to mplement my own OneOf class and it works:

class OneOf&lt;T1, T2&gt; {
  T1? _result1;
  T2? _result2;

  OneOf.formResult(dynamic result) {
    if (result is T1) {
      _result1 = result;
    } else if (result is T2) {
      _result2 = result;
    }
  }

  handle(
      {required void Function(T1?) handleT1,
      required void Function(T2?) handleT2}) {
    if (_result1 != null) {
      handleT1(_result1);
    } else if (_result2 != null) {
      handleT2(_result2);
    }
  }
}

as you can see the implementation uses two generic types, and you can handle the results with the handle function, now I want to have the three generics implementation, but Dart don't allow to have a class with the same name even when they handle a different number of generic parameters (I come from c# and there it is allowed).

is there a way to have a variable amount of generic arguments in the class? or is there another solutin that I'm not seeeing for being new in the language?

for the curious the usage of this class would look like this

var message = &quot;Hello world!!&quot;;
var result = OneOf&lt;bool, String&gt;.formResult(mensaje);

result.handle(
  handleT1: (boolResult) {
    print(
        &quot;I have reeived a boolean&quot;);
},
                  handleT2: (stringResult) {
    print(&quot;I have received the string &#39;$message&#39;&quot;);
},

答案1

得分: 0

很遗憾,没有办法实现可变数量的通用参数。

我能想到的唯一其他方法是使用某种带有动态类型的辅助方法。
缺点是你没有静态类型并且必须将结果转换。

这是一些示例代码:

typedef Handler = dynamic Function(dynamic);

dynamic oneOf(dynamic result, Map&lt;Type, Handler&gt; handlers) {
  if (handlers.containsKey(result.runtimeType)) {
    return handlers[result.runtimeType]!.call(result);
  } else {
    throw Exception(&quot;some error, because no handler was provided for $result&quot;);
  }
}

void useOneOf() {
  const String message = &quot;Hello world!!&quot;
  const int number = 123;

  final Map&lt;Type, Handler&gt; handlers = &lt;Type, Handler&gt;{
    String: (dynamic input) =&gt; (input as String).toUpperCase(),
    int: (dynamic input) =&gt; (input as int) * 2,
  };

  final String result1 = oneOf(message, handlers) as String;
  final int result2 = oneOf(number, handlers) as int;
  print(result1); // &quot;HELLO WORLD!!&quot;
  print(result2); // 246
  final bool exception = oneOf(false, handlers) as bool; // throws exception
}
英文:

Sadly there is no way to implement a variable amount of generic arguments.

The only other thing i can think of is using some kind of helper method with dynamic types instead.
The downside is that you don't have the static types and have to cast the results.

This is some sort of example code:

typedef Handler = dynamic Function(dynamic);

dynamic oneOf(dynamic result, Map&lt;Type, Handler&gt; handlers) {
  if (handlers.containsKey(result.runtimeType)) {
    return handlers[result.runtimeType]!.call(result);
  } else {
    throw Exception(&quot;some error, because no handler was provided for $result&quot;);
  }
}

void useOneOf() {
  const String message = &quot;Hello world!!&quot;;
  const int number = 123;

  final Map&lt;Type, Handler&gt; handlers = &lt;Type, Handler&gt;{
    String: (dynamic input) =&gt; (input as String).toUpperCase(),
    int: (dynamic input) =&gt; (input as int) * 2,
  };

  final String result1 = oneOf(message, handlers) as String;
  final int result2 = oneOf(number, handlers) as int;
  print(result1); // &quot;HELLO WORLD!!&quot;
  print(result2); // 246
  final bool exception = oneOf(false, handlers) as bool; // throws exception
}

huangapple
  • 本文由 发表于 2023年7月3日 09:20:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76601354.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定