一、需求来源
平时遇到使用 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 可用于处理一些越界情况。