使用通用回调冻结 class

Freezed class with generic callback

我想定义一个带有通用回调的冻结 class [https://pub.dev/packages/freezed]。

冻结class:

import 'package:freezed_annotation/freezed_annotation.dart';

part 'foo.freezed.dart';

@freezed
abstract class Foo<T> with _$Foo {
  factory Foo({
    // String Function() callBackOne,
    String Function(T) callBackTwo,
  }) = _Foo;
}

使用冻结 class 的小部件:

class MyHomePage extends StatelessWidget {
  // final fooOne = Foo<int>(callBackOne: () => 'Result: 42');
  final fooTwo = Foo<int>(callBackTwo: (value) => 'Result: ${value * 3}');
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(fooTwo.callBackTwo(14)),
      ),
    );
  }
}

错误:

lib/foo.freezed.dart:128:26: Error: The return type of the method '_Foo.callBackTwo' is 'String Function(T)', which does not match the return type, 'String Function(dynamic)', of the overridden method, '_$Foo.callBackTwo'.
Change to a subtype of 'String Function(dynamic)'.
  String Function(T) get callBackTwo;
                         ^
lib/foo.freezed.dart:31:26: Context: This is the overridden method ('callBackTwo').
  String Function(T) get callBackTwo;

                         ^

你知道我的代码有什么问题吗?这是冻结的限制吗?您知道解决方法吗?

谢谢!!!

这看起来像是 Dart 类型系统中的一个缺陷。我也鼓励过类似的事情。我不知道一个干净的解决方法。您可以指定的不是直接函数,而是包装到具有“强”方法签名的 class 中的函数。类似的东西应该可以工作:

@freezed
abstract class Foo<T> with _$Foo {
  factory Foo({
    Func<T> callBackTwo,
  }) = _Foo;
}

class Func<T> {
  final String Function(T) _apply;

  Func(this._apply) : assert(_apply != null);

  String call(T value) {
    return _apply(value);
  }
}

class MyHomePage extends StatelessWidget {    
  final fooTwo = Foo<int>(Func<int>((value) => 'Result: ${value * 3}'));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(fooTwo.callBackTwo(14)),
      ),
    );
  }
}

不太好,因为你要打更多字。但我们可以尽量减少打字:

@freezed
abstract class Foo<T> with _$Foo {
  factory Foo({
    Func<T> callBackTwo,
  }) = _Foo;

  factory Foo.from(String Function(T) arg) {
    return Foo<T>(callBackTwo: Func<T>(arg));
  }
}

class MyHomePage extends StatelessWidget {    
  final fooTwo = Foo<int>.from((value) => 'Result: ${value * 3}');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(fooTwo.callBackTwo(14)),
      ),
    );
  }
}