代码之家  ›  专栏  ›  技术社区  ›  Thierry

使用泛型回调冻结类

  •  0
  • Thierry  · 技术社区  · 5 年前

    我想定义一个冻结类[https://pub.dev/packages/freezed]使用通用回调。

    冻结类:

    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 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;
    
                             ^
    

    你知道我的代码有什么问题吗?这是冷冻食品的限制吗?你知道解决办法吗?

    非常感谢。

    0 回复  |  直到 5 年前
        1
  •  1
  •   ChessMax    5 年前

    它看起来像是飞镖式系统中的一个缺陷。我也鼓励过类似的事情。我不知道一个干净的解决办法。您可以指定一个函数,而不是直接函数,而是一个封装到带有“强”方法签名的类中的函数。类似的方法应该会奏效:

    @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)),
          ),
        );
      }
    }