【问题标题】:How can I initialize a mixin's immutable data in Dart?如何在 Dart 中初始化 mixin 的不可变数据?
【发布时间】:2019-06-07 13:52:37
【问题描述】:

我正在使用 Dart 2.1.0 在 Flutter 中编程,遇到这种情况:

mixin Salt {
  final int pinches;  // Immutable, and I want to delay initialization.

  // Cannot declare constructors for mixin
}

class Meat with Salt {
  Meat(int pinches) ... // How to initialize it?
}

Salt 没有构造函数,所以我不能使用初始化列表。 pinchesfinal,所以我不能在Meat 的构造函数中设置它。

我不想让Salt 成为一个类,因为Meat 可能需要从其他东西扩展。

我想保持pinches 不可变。

有什么办法吗?提前致谢。

【问题讨论】:

    标签: dart flutter mixins final


    【解决方案1】:

    您可以将 mixin 的声明更改为:

    mixin Salt {
      int get pitches;
    }
    

    然后在实现类里面定义字段

    class Meat with Salt {
      final int pitches;
      Meat(this.pitches);
    } 
    

    【讨论】:

    • 在这种情况下使用mixin有什么意义,如果我们应该这样复制代码?
    • Mixins 不用于声明变量。但是对于可重用的方法,而不是
    • @RémiRousselet 如何在 Flutter 上进行初始化? DemiLogic 是混入 class _DemoPageState extends State<DemoPage> with DemoLogic {
    【解决方案2】:

    按照设计,不可能将 final 成员声明到 mixin 中,因为无法声明构造函数来初始化 final 成员, 引用the docs:

    但是,在这个提议中,mixin 只能从没有声明构造函数的类中提取。这种限制避免了由于需要将构造函数参数向上传递到继承链而出现的复杂情况。

    折衷方案可能是声明一个私有成员并仅实现一个 getter。
    _pinches 仅在库内部可见,对库用户是只读的。

    mixin Salt {
      int _pinches;
    
      get pinches => _pinches;
    
    }
    
    class Meat with Salt {
    
      Meat(int pinches)  {
       _pinches = pinches;
      }
    }
    

    注意:由于可见性规则,上述模式仅在 mixin 和混合类位于同一个库中时才有效。

    【讨论】:

    • 只有当SaltMeat 在同一个库中声明时才有效,否则_pinches 将无法访问。
    • 我可以接受两个答案,因为@attdona 和@RémiRousselet 一起给出了全貌吗? @RémiRousselet 的建议可行,但它违背了在 mixins 中保存数据的目的。在@attdona 的建议中,_pinches 并不是严格不可变的。你们一起确认没有理想的解决方案。我对这两个答案都投了赞成票,但很抱歉没有(完全)接受。
    【解决方案3】:

    类似于attdona的建议,但更接近你真正想要的,你可以这样做

    mixin Salt {
      int _pinches;
      int get pinches => _pinches;
      void initSalt(int pinches) {
        assert(_pinches == null);
        _pinches = pinches;
      }
    }
    
    class Meat with Salt {
      Meat(int pinches) {
        initSalt(pinches);
      }
    }
    

    严格来说它仍然不是最终的,但是(只要 mixin 在不同的库中,因此您不能直接更改私有成员)它在运行时是不可变的。不如它可能是正确的最终结果那么好,但可能足够接近。

    【讨论】:

      【解决方案4】:

      以下方法可以让你在以后设置数据,并摆脱警告:

      This class (or a class that this class inherits from) is marked as '@immutable', but one or more of its instance fields aren't final

      mixin Salt {
        final SaltData _saltData = SaltData();
      
        int get pinches => _saltData.pinches;
      
        set pinches(int extraData) {
          _saltData.pinches = extraData;
        }
      }
      
      class SaltData {
        int pinches = 0;
      }
      

      所以我所做的是创建一个类SaltData。这将存储您需要的所有变量。

      私有_saltData 变量是最终的,这将停止警告。

      然后使用 getter 和 setter 来检索和更新数据。

      int get pinches => _saltData.pinches;
      
      set pinches(int extraData) {
        _saltData.pinches = extraData;
      }
      

      如果您愿意,您也可以公开整个 saltData 对象:

      SaltData get saltData => _saltData;

      【讨论】:

        【解决方案5】:

        我对此提出了我的解决方案。通过标记变量late,您可以将其设为final。初始化失败不会出现警告,请谨慎使用。

        mixin Salt {
          late final int pinches;
        }
        
        class Vegetable with Salt {
          Vegetable(int pinches) {
            this.pinches = pinches;
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-14
          • 2013-08-31
          • 2021-03-09
          • 2019-07-12
          • 1970-01-01
          • 1970-01-01
          • 2020-04-14
          • 1970-01-01
          相关资源
          最近更新 更多