0.闲谈
2020年,一场突如起来的疫情,打乱了全国千千万万人的正常生活,也很庆幸,自己在情况最危险的时候之前,离开了武汉回到了家中。所有人都强制要求不能出门,经过1个多月的最严格的全方面把控,疫情似乎逐渐正在消退,十分感激那些奋战在前线的白衣工作者和千千万工作人员,中国加油!
1.接口之间的继承
最近在做SimpleDB这个项目,让我印象很深的地方就是接口和具体实现类的设计这一块。其中,有一个点很想记下来,那就是接口的继承,原来几乎没用过这个策略。
我们都知道,接口表达的就是某个对象具有的功能,而该功能的具体实现由具体实现该接口的类来负责。
我们也知道在SQL中,大致存在两类SQL语句:① SQL查询语句 ② SQL更新语句,前者只会读取数据库表的值,而后者会修改相应值,在代码实现的时候,二者分别对应实现了Scan
接口和UpdateScan
接口。而Plan类中会有一个创建具体Scan对象的opne()
方法。
上述的接口代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23interface Scan {
// 移动到第一条记录之前
public void beforeFirst() throws IOException;
// 移动到下一条记录,如果没有下一条记录,返回false
public boolean next() throws IOException;
// 关闭scan,如果有subScan,也会相应关闭
public void close() throws IOException;
// 获取当前记录指定字段的值,被抽象成了一个Constant对象
public Constant getVal(String fieldName);
// 获取当前字段指定int字段的值
public int getInt(String fieldName);
// 获取当前字段指定string字段的值
public String getString(String fieldName);
// 判断是否有指定字段
public boolean hasField(String fieldName);
}
1 | public interface UpdateScan extends Scan { |
1 | public interface Plan { |
到时候,包含where子句的更新SQL语句会对应创建一个SelectPlan
对象,而该对象的open()方法又会创建一个UpdateScan对象,这样一来,Plan
接口可以有不同的实现,而不管具体的实现是什么,open()方法也必然会返回一个Scan
对象。
此外,实现了UpdateScan
接口的具体类又可能会持有一个实现了Scan
接口或UpdateScan
接口的实例,这样一来,就可以将该实例变量的类型声明为Scan
即可,具体是什么类型,交给具体实现类去处理即可。例如SelectScan
类的代码: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
98public class SelectScan implements UpdateScan {
private Scan scan;
private Predicate predicate;
public SelectScan(Scan scan, Predicate predicate) {
this.scan = scan;
this.predicate = predicate;
}
//================Scan 接口中的方法实现===================
public void beforeFirst() throws IOException {
scan.beforeFirst();
}
public boolean next() throws IOException {
// 这里必须用while,而不是if
while (scan.next())
if (predicate.isSatisified(scan))
return true;
return false;
}
public void close() throws IOException {
scan.close();
}
public Constant getVal(String fieldName) {
return scan.getVal(fieldName);
}
public int getInt(String fieldName) {
return scan.getInt(fieldName);
}
public String getString(String fieldName) {
return scan.getString(fieldName);
}
public boolean hasField(String fieldName) {
return scan.hasField(fieldName);
}
//================UpdateScan 接口中额外的方法实现===================
public void setVal(String fieldName, Constant newVal) {
// 这里必须把scan强转为UpdateScan类型
// 也只有UpdateScan类型的对象才有setXXX()方法
// 如果scan不是一个实现了UpdateScan接口的对象,运行时则会抛出ClassCastException异常
UpdateScan updateScan = (UpdateScan) scan;
updateScan.setVal(fieldName,newVal);
}
public void setInt(String fieldName, int newVal) {
UpdateScan updateScan = (UpdateScan) scan;
updateScan.setInt(fieldName, newVal);
}
public void setString(String fieldName, String newVal) {
UpdateScan updateScan = (UpdateScan) scan;
updateScan.setString(fieldName, newVal);
}
public void insert() throws IOException {
UpdateScan updateScan = (UpdateScan) scan;
updateScan.insert();
}
public void delete() {
UpdateScan updateScan = (UpdateScan) scan;
updateScan.delete();
}
public RID getRID() {
UpdateScan updateScan = (UpdateScan) scan;
return updateScan.getRID();
}
public void moveToRId(RID rid) {
UpdateScan updateScan = (UpdateScan) scan;
updateScan.moveToRId(rid);
}
}
2.抽象类
抽象类就是有一个或多个方法没有实现的类,个人感觉,抽象类的更多的应用场景是结合了接口的。比如说某个接口HelloWorld
,该接口中有2个方法,一个是输出hello world!
这个字符串;还有一个方法是输出本地语言中和hello world同义的字符串。1
2
3
4interface HelloWorld{
public String sayHelloWorld();
public String sayLocalHelloWorld();
}
于是我们可以设计一个抽象类AbstractHelloWorld
,该抽象类固定好了第一个方法sayHelloWorld()
的实现,而把第二个方法的实现交给具体的实现者:1
2
3
4
5
6abstract class AbstractHelloWorld implements HelloWorld {
public String sayHelloWorld() {
return "hello world!";
}
}
最后,我们只要实现一个继承AbstractHelloWorld
类的具体实现类即可,例如``:1
2
3
4
5
6public class ChineseHelloWorld extends AbstractHelloWorld {
public String sayLocalHelloWorld() {
return "你好,世界!";
}
}
说到底,抽象类就是方便程序员不要完完全全实现接口中的所有方法,抽象类将接口中那些不太会变化的方法实现好,其他程序员只要继承抽象类,去实现接口中那些经常会发生变化的方法即可(也就是抽象类中没有实现的方法)。