And*_*ács 13 java haskell interface
在Haskell(和Rust等)中,我可以拥有受其他实例约束的实例:
data Pair a b = Pair a b
instance (Eq a, Eq b) => Eq (Pair a b) where
Pair a b == Pair a' b' = a == a' && b == b'
Run Code Online (Sandbox Code Playgroud)
使用Java接口我不能.我必须要求类型参数Pair
始终实现Eq
,否则我根本无法实现Eq<Pair<A, B>>
:
interface Eq<A> {
public boolean eq(A other);
}
class Pair<A extends Eq<A>, B extends Eq<B>> implements Eq<Pair<A, B>> {
A a;
B b;
public boolean eq(Pair<A, B> other){
return a.eq(other.a) && b.eq(other.b);
}
}
Run Code Online (Sandbox Code Playgroud)
我希望有类似的东西:
class Pair<A, B> implements Eq<Pair<A, B>> if (A implements Eq<A> && B implements Eq<B>) {...}
Run Code Online (Sandbox Code Playgroud)
到目前为止,互联网告诉我,Java中没有直接支持我所需的功能.尽管如此,我发现这是接口(重新)可用性的一个相当关键的因素.我想知道是否有大致覆盖相同基础的变通方法或解决方案.
我想到的一个规范解决方案是让比较器在类外部.这是Scala采用的方法,同时借助implicits使其易于消化.他们你有建立比较器的方法,比如
public <A, B> Comparator<Pair<A,B>> pairCmp(Comparator<A> ca, Comparator<B> cb) { ...
Run Code Online (Sandbox Code Playgroud)
然而,使用起来非常麻烦.Haskell在内部做同样的事情,传递类型类实现的字典,但类型类接口和类型推断使它更愉快.
据我所知,在Java中,如何声明条件实例是没有办法的.但更为面向对象的方法是为允许相等的对提供子类:
class PairEq<A extends Eq<A>, B extends Eq<B>>
extends Pair<A,B>
implements Eq<Pair<A, B>> {
...
Run Code Online (Sandbox Code Playgroud)
还需要一些手动过程,因为您需要决定何时使用Pair
以及何时使用PairEq
.但是通过方法重载,我们可以通过声明智能构造函数来使其更容易使用.由于Java总是选择最具体的一个,每当我们需要创建一对时,我们只是使用,如果参数适当地实现mkPair
,Java将选择返回的一个:PairEq
Eq
public static <A,B> Pair<A,B> mkPair(A a, B b) {
return new Pair<A,B>(a, b);
}
public static <A extends Eq<A>, B extends Eq<B>> PairEq<A,B> mkPair(A a, B b) {
return new PairEq<A,B>(a, b);
}
Run Code Online (Sandbox Code Playgroud)
完整示例代码:
interface Eq<A> {
public boolean eq(A other);
}
public class Pair<A,B> {
public final A a;
public final B b;
public Pair(A a, B b) {
this.a = a;
this.b = b;
}
public static <A,B> Pair<A,B> mkPair(A a, B b) {
return new Pair<A,B>(a, b);
}
public static <A extends Eq<A>, B extends Eq<B>> PairEq<A,B> mkPair(A a, B b) {
return new PairEq<A,B>(a, b);
}
}
class PairEq<A extends Eq<A>, B extends Eq<B>>
extends Pair<A,B>
implements Eq<Pair<A,B>>
{
public PairEq(A a, B b) {
super(a, b);
}
@Override
public boolean eq(Pair<A,B> that) {
return a.eq(that.a) && b.eq(that.b);
}
}
Run Code Online (Sandbox Code Playgroud)
嗯...不。
但是我们可以有一个方便的方法,将 a “转换”Pair<A,B>
为 an Eq<Pair<A,B>>
,如果A,B
两者Eq
也是的话。这需要在使用现场执行额外的步骤,并且程序员必须在需要时进行显式类型转换;但这可能还不错
class Pair<A, B>
{
A a;
B b;
}
static
<A extends Eq<A>, B extends Eq<B>>
Eq<Pair<A,B>> cast(Pair<A,B> p1)
{
return p2->( p1.a.eq(p2.a) && p1.b.eq(p2.b) );
}
--
Pair<X,Y> pair = ...;
Eq<Pair<X,Y>> eq = cast(pair);
Run Code Online (Sandbox Code Playgroud)
最好,我们希望将强制转换方法作为实例方法,例如
Eq<Pair<X,Y>> eq = pair.asEq();
Run Code Online (Sandbox Code Playgroud)
然而,我们不希望它编译,除非X,Y
满足约束。强制执行的一种方法
class Pair<A, B>
{
A a;
B b;
<A2 extends Eq<A>, B2 extends Eq<B>>
Eq<Pair<A2,B2>>
asEq()
{
return p2->( p2.a.eq(a) && p2.b.eq(b) );
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
281 次 |
最近记录: |