Flutter进阶:Comparable协议扩展

215 阅读1分钟

一、需求来源

平时遇到使用 num 的 clamp 的函数的时候就感觉特别好用,就想扩展到任何类型。但是一直没有思路,直到昨天基于 Comparable 重载运算符的时候突然灵光一闪,这不是我一直思而不得的东西吗,然后立马实现,分享给大家。

clamp 源码

/// Example:
/// ```dart
/// var result = 10.5.clamp(5, 10.0); // 10.0
/// result = 0.75.clamp(5, 10.0); // 5
/// result = (-10).clamp(-5, 5.0); // -5
/// result = (-0.0).clamp(-5, 5.0); // -0.0
/// ```
num clamp(num lowerLimit, num upperLimit);

二、使用示例

final now = DateTime.now();
final before = now.subtract(Duration(hours: 1));
final after = now.add(Duration(hours: 1));

final d1 = Duration(hours: 1);
final d2 = Duration(hours: 2);
DLog.d("now: $now");
DLog.d("before: $before");
DLog.d("after: $after");
DLog.d("now.inRange(before, after): ${now.inRange(before, after)}");
DLog.d("before.clamp(now, after): ${before.clamp(now, after)}");
DLog.d("now > before: ${now > before}");
DLog.d("now > after: ${now > after}");
DLog.d("d1 > d2: ${d1 > d2}");
DLog.d("d1 < d2: ${d1 < d2}");


// [log] DLog 2024-11-09 09:47:02.634885 now: 2024-11-09 09:47:02.634465
// [log] DLog 2024-11-09 09:47:02.635243 before: 2024-11-09 08:47:02.634465
// [log] DLog 2024-11-09 09:47:02.635631 after: 2024-11-09 10:47:02.634465
// [log] DLog 2024-11-09 09:47:02.635907 now.inRange(before, after): true
// [log] DLog 2024-11-09 09:47:02.636189 before.clamp(now, after): 2024-11-09 09:47:02.634465
// [log] DLog 2024-11-09 09:47:02.636434 now > before: true
// [log] DLog 2024-11-09 09:47:02.636705 now > after: false
// [log] DLog 2024-11-09 09:47:02.636899 d1 > d2: false
// [log] DLog 2024-11-09 09:47:02.637086 d1 < d2: true

三、源码

generic_comparable_ext.dart 源码

//
//  GenericComparableExt.dart
//  flutter_templet_project
//
//  Created by shang on 2024/11/8 16:03.
//  Copyright © 2024/11/8 shang. All rights reserved.
//

extension GenericComparableExt<T extends Comparable<T>> on T {
  /// > 运算符重载
  bool operator >(T value) => compareTo(value) > 0;

  /// < 运算符重载
  bool operator <(T value) => compareTo(value) < 0;

  /// 是否在区间之内
  bool inRange(T lowerLimit, T upperLimit) {
    final result = compareTo(lowerLimit) >= 0 && compareTo(upperLimit) <= 0;
    // debugPrint("inRange ${{
    //   "lowLimit": lowLimit.toString(),
    //   "this": toString(),
    //   "highLimit": highLimit.toString(),
    // }}");
    return result;
  }

  /// 超出底限用底限, 超出上限用上限
  T clamp(T lowerLimit, T upperLimit) {
    if (compareTo(lowerLimit) < 0) {
      return lowerLimit;
    }

    if (compareTo(upperLimit) > 0) {
      return upperLimit;
    }
    return this;
  }
}

最后、总结

  • 因为各个类型的实现对比算法不一致,且存在未来调整的可能,所以我们有且只有一种办法给所有类型实现比较:就是基于 Comparable 的结果作比较。
  • 重载运算符是为了方便实例比较。
  • inRange 可用于处理一些越界情况。

github