主要就是为了吐槽 GO
模板方法
在绝大多数的 OOP
语言中,我们都希望,我们可能在父类中完成绝大多数的任务,子类仅仅完成一部分的任务即可。
1 2 3 4 5 6 7
| public interface Named { String name();
default String firstName() { return name().split("/")[0]; } }
|
当我们实现 EN
和 CN
的版本时候,只需要。
1 2 3 4 5 6
| class EnglishNamed implements Named{ @Override public String name() { return "jack/ma"; } }
|
1 2 3 4 5 6
| class ChineseNamed implements Named { @Override public String name() { return "春/天"; } }
|
对于获取 FirstName
的逻辑是一致的。
那如果我们使用 GO
来实现的话。
1 2 3 4 5 6 7 8 9 10
| type EnglishNamed struct { }
func (e *EnglishNamed) Name() string { return "jack/ma" }
func (e *EnglishNamed) FirstName() string { return strings.Split(e.Name(), "/")[0] }
|
1 2 3 4 5 6 7 8 9 10 11
| type ChineseNamed struct { }
func (e *ChineseNamed) Name() string { return "jack/ma" }
func (e *ChineseNamed) FirstName() string { return strings.Split(e.Name(), "/")[0] }
|
我们发现其实我们有一个 重复的
代码。为了让这个代码不重复,单纯的依靠组合不能够达成。我们需要修改下实现的方式,重新定义
1 2 3 4 5 6 7 8 9
| type Name string
type Named interface { Name() Name }
func (n Name) FirstName() string { return strings.Split(string(n), "/")[0] }
|
然后我们再来实现对象
1 2 3 4 5 6
| type EnglishNamed struct { }
func (e *EnglishNamed) Name() Name { return "jack/ma" }
|
1 2 3 4 5 6
| type ChineseNamed struct { }
func (e *ChineseNamed) Name() Name { return "jack/ma" }
|
使用 Rust
我们可以实现和 Java
类似的代码。go
缺失在 inteface
没有 default method
Deep Equal
我们经常会有这么一个需求,比如我有一个对象 A,包含了对象 B,又包含了对象 C,我希望 C.xxx 字段如果是 True 就进行一些处理
基础定义1 2 3 4 5 6 7 8 9 10 11
| type A struct { B *B }
type B struct { C *C }
type C struct { Flag bool }
|
如果是 go
只能写出如下代码
1 2 3 4 5
| func ifDo(a *A) { if a != nil && a.B != nil && a.B.C != nil && a.B.C.Flag { } }
|
而对比之下,Java 可以写出略微优雅的代码
1 2 3 4 5 6 7
| public void ifDo(A a){ Boolean ifCondition = Optional.ofNullable(a) .map(A::getB) .map(B::getC) .map(C::isFlag) .orElse(false); }
|
而到了 Rust | kotlin
我们可以借助于语法糖
1 2 3 4 5 6 7 8
| fn doIf(a: Option<A>) -> Option<bool> { match a?.b?.c { Some(it) => { return Option::Some(it.flag); } _ => Option::None } }
|