Pattern matching in Java(续)

上一篇文章里翻译了java8以前模式匹配在java中的使用情况.
这一篇文章会简单介绍cyclops库中模式匹配的相关内容.
cyclops是基于java8的一个扩展库,包括了模式匹配,stream工具类,monad,元组等内容.

直接上完整的代码.handleByType方法匹配类型,handleByValue方法匹配值.
isType方法传入一个名为TypedFunction的函数式接口,这个接口里有一个默认方法可以获取lanbda表达式中的泛型具体类型.
需要注意的是当需要值匹配时必须重写类的equals方法,因为Object中的equals方法认为两个不同的对象是不相等的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package org.gradle.pattern;

import org.junit.Test;

import com.aol.cyclops.matcher.builders.Matching;

public class Patterns {

abstract class Foo {

}

class Bar extends Foo {

public Bar(Integer bar) {
super();
this.bar = bar;
}

private Integer bar;

public Integer getBar() {
return bar;
}

public void setBar(Integer bar) {
this.bar = bar;
}

}

class Baz extends Foo {

public Baz(String baz) {
super();
this.baz = baz;
}

private String baz;

public String getBaz() {
return baz;
}

public void setBaz(String baz) {
this.baz = baz;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + ((baz == null) ? 0 : baz.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Baz other = (Baz) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (baz == null) {
if (other.baz != null)
return false;
} else if (!baz.equals(other.baz))
return false;
return true;
}

private Patterns getOuterType() {
return Patterns.this;
}

}

Object handleByType(Foo foo) {
return Matching
.when().isType((Bar bar) -> bar.getBar())
.when().isType((Baz baz) -> baz.getBaz())
.match(foo)
.get();
}

Object handleByValue(Foo foo) {
return Matching
.when().isValue(new Baz("Luhrmann")).thenApply(baz -> baz.getBaz())
.match(foo)
.orElse("match nothing");
}

@Test
public void test() {
System.out.println(handleByType(new Bar(42))); // 42
System.out.println(handleByType(new Baz("letty"))); // letty
System.out.println(handleByValue(new Baz("Luhrmann"))); // Luhrmann
System.out.println(handleByValue(new Baz(""))); // match nothing
}
}

虽然和scala中的guard和case class相比,java中的模式匹配还是不够灵活,
然而这毕竟缺少了语言层面的支持.尽管如此,使用cyclops还是比起用访问者模式
在可读性和实现的难易度上都大大进步了.
预告:下一篇博客可能会继续介绍cyclops,或者是和动静态语言相关的内容.