java重载运算符
Manifold扩展依赖项插入Java中,以提供无缝的运算符重载功能。 通过实现一个或多个预定义的运算符方法,可以为任何类类型安全地提供算术,关系和单位运算符 。 您可以直接在您的类中实现运算符方法,也可以使用扩展方法为您原本无法控制的类实现运算符。 例如,使用扩展方法Manifold为BigDecimal
提供了运算符实现,因此您可以编写如下代码:
BigDecimal result = bigValue1 + bigValue2;
使用单位表达式,可以更轻松地使用BigDecimal
和其他类型:
BigDecimal result = 3.14bd * 10.75bd; // `bd` makes BigDecimals
通过单元和操作员过载进行精确测量:
Length distance = 65 mph * 3.2 hr;
HeatCapacity kBoltzmann = 1.380649e-23r J/dK;
算术和否定运算符
任何类型都可以通过实现以下一种或多种运算符方法来支持算术运算符:
算术
操作方式 | 方法 |
---|---|
a + b | a.plus(b) |
a - b | a.minus(b) |
a * b | a.times(b) |
a / b | a.div(b) |
a % b | a.rem(b) |
否定
操作方式 | 方法 |
---|---|
-a | a.unaryMinsu() |
注意运算符方法不属于您实现的类或接口。 相反,您可以通过定义具有相同签名的方法来简单地在结构上实现它们。 请注意,您可以实现同一方法的多个不同版本,具体取决于参数类型。
这是一个简单的示例,演示如何实现+
运算符:
public class Point {
public final int x, y;
public Point(int x, int y) {this.x = x; this.y = y;}
public Point plus(Point that) {
return new Point(x + that.x, y + that.y);
}
}
var a = new Point(1, 2);
var b = new Point(3, 4);
var sum = a + b; // Point(4, 6)
由于运算符方法是结构性的,因此可以定义多个 plus()
方法:
public Point plus(int[] coord) {
if(coord.length != 2) {
throw new IllegalArgumentException();
}
return new Point(x + coord[0], y + coord[1]);
}
关系运算符
您可以使用ComparableUsing
和/或Comparable
接口的组合来实现关系运算符。
manifold.ext.api.ComparableUsing
关系运算符可以与ComparableUsing
接口一起全部实现,该接口扩展了Comparable
以提供特定于运算符的API。
boolean compareToUsing( T that, Operator op );
其中Operator
是一个enum
,它为关系运算符指定常数。
操作方式 | 可比的使用Impl | 可比的Impl |
---|---|---|
a > b | a.compareToUsing(b, GT) | a.compareTo(b) > 0 |
a >= b | a.compareToUsing(b, GE) | a.compareTo(b) >= 0 |
a < b | a.compareToUsing(b, LT) | a.compareTo(b) < 0 |
a <= b | a.compareToUsing(b, LE) | a.compareTo(b) <= 0 |
ComparableUsing
提供了compareToUsing()
的默认实现,该默认实现委托给关系运算符的>
, >=
, <
和<=
子集的Comparable
的compareTo()
实现。 对于==
和!=
子集, ComparableUsing
委托给该类型的equals()
方法(稍后将详细介绍平等性)。 此行为适用于大多数类型,因此通常您只需要向您的类型的implements
或extends
子句中添加ComparableUsing
即可ComparableUsing
仅实现Comparable
。 因此,在Point
示例中增加了关系运算符支持:
public class Point implements ComparableUsing {
public final int x, y;
public Point(int x, int y) {this.x = x; this.y = y;}
public Point plus(Point that) {
return new Point(x + that.x, y + that.y);
}
public int compareTo(Point that) {
return x - that.x;
}
}
现在,您可以像这样轻松地比较“点”值:
if (pt1 >= pt2) ...
java.lang.Comparable
如果您对支持==
和!=
不感兴趣,并且您的类型实现了Comparable
接口,它将自动支持关系运算符的>
, >=
, <
和<=
子集。 例如,既java.lang.String
和java.time.LocalDate
实现compareTo()
从方法Comparable
,这意味着它们可以在关系表达式中使用的:
String name1;
String name2;
...
if (name1 > name2) {...}
LocalDate date1;
LocalDate date2;
...
if (date1 > date2) {...}
还请参见:
平等经营者
要实现关系运算符的==
和!=
子集,必须实现ComparableUsing
接口。 默认情况下, ComparableUsing
委托给您类型的equals()
方法,但是您可以通过重写CopmarableUsing
实现中的CopmarableUsing
equalityMode()
方法来轻松覆盖此行为。 EqualityMode
枚举提供了可用的模式:
/**
* The mode indicating the method used to implement {@code ==} and {@code !=} operators.
*/
enum EqualityMode
{
/** Use the {@code #compareTo()} method to implement `==` and `!=` */
CompareTo,
/** Use the {@code equals()} method to implement `==` and `!=` (default) */
Equals,
/** Use {@code identity} comparison for `==` and `!=`, note this is the same as Java's normal {@code ==} behavior } */
Identity
}
根据您的CompareToUsing#equalityMode()
实现返回的EqualityMode
, ==
和!=
运算符使用以下方法进行编译:
操作方式 | Equals <small>(默认)</ small> | CompareTo | Identity |
---|---|---|---|
a == b | a.equals(b) | a.compareToUsing(b, EQ) | a == b |
a != b | !a.equals(b) | a.compareToUsing(b, NE) | a != b |
注意:歧管为==
和!=
生成有效的, 空安全的代码。 例如,使用Equals
模式的a == b
编译为:
a == b || a != null && b != null && a.equals(b) If you need something more customized you can overridecompareToUsing()
with your own logic for any of the operators, including==
and!=
. To enable==
onPoint
more effectively, you can accept the default behavior ofComparableUsing
and implementequals()
:
public boolean equals(Object that) {
return this == that || that != null && getClass() == that.getClass() &&
x == ((Point)that).x && y == ((Point)that).y;
}
请注意,如果实现
equals()
,请始终考虑实现hashCode()
,否则在与Map
和其他数据结构一起使用时,您的类型可能无法正常工作:public int hashCode() { return Objects.hash(x, y); }
有时最好使用CompareTo
模式。 例如, Rational
, BigDecimal
和BigInteger
的==
和!=
实现使用CompareTo
模式,因为在那些类中, compareTo()
反映了它们所建模数字的面值的相等性,例如1.0 == 1.00,即在许多用例中的期望行为。 在那种情况下,只需重写equalityMode()
以返回CompareTo
:
@Override
public EqualityMode equalityMode() {
return CompareTo;
}
还请参见:
单位经营者
单位或“绑定”操作对于歧管框架是唯一的。 它们提供了功能强大且简洁的语法,可以应用于广泛的应用程序。 您可以使用prefixBind()
和postfixBind()
方法实现运算符:
操作方式 | 后缀绑定 | 前缀绑定 |
---|---|---|
ab | b.postfixBind(a) | a.prefixBind(b) |
如果类型a
工具R prefixBind(B)
其中B
距离的类型分配的b
,则ab
编译作为方法调用a.prefixBind(b)
具有式R
否则,如果类型b
器具R postfixBind(A)
其中A
是从分配的类型a
,然后ab
编译作为方法调用b.postfixBind(a)
具有式R
此功能启用以下表达式:
Mass m = 5 kg;
Force f = 5 kg * 9.8 m/s/s;
for (int i: 1 to 10) {...}
阅读更多有关单位表达式的信息 。
扩展方法运算符
使用扩展方法,您可以为原本无法控制的类提供操作员实现。 例如,Manifold为BigDecimal
和BigInteger
提供了运算符扩展。 这些扩展是在manifold-science
依赖中实现的。
这是BigDecimal
的+
扩展名:
@Extension
public abstract class ManBigDecimalExt implements ComparableUsing {
/** Supports binary operator {@code +} */
public static BigDecimal plus(@This BigDecimal thiz, BigDecimal that) {
return thiz.add(that);
}
...
}
```
Now you can perform arithmetic and comparisons using operator expressions:
```java
if (bd1 >= bd2) {
BigDecimal result = bd1 + bd2;
. . .
}
请注意,
manifold-science
和manifold-collections
模块广泛使用运算符重载和单位表达式。
翻译自: https://jaxenter.com/manifold-operator-overloading-java-163232.html
java重载运算符