最近长期沉迷于win,无心切到Linux下面码代码(各种IDE都装在Linux里面),昨天突然想做个模型,就随手打开个记事本开始写了。第一直觉是用最近几年用得最多的Java写,但是很快就发现脱离IDE要写出合法的Java代码其实是一件很麻烦的事情。
Java的语法和默认的一些原则的确是又臭又长。不得不说跑在JVM上的其他一些语言的语法糖的确有可取之处,至少当我用记事本写代码的时候是深深的这么觉得的。
比如给成员变量加上private修饰,仅仅访问就需要用getter和setter,这种约定俗成的做法就很不科学。因为Java无修饰的可访问范围是包,这实际上是一个很安全的范围,完全可以大大方方的使用,同包内直接访问。或者使用类似c#的get和set这样的修饰,把public修饰拆分成两部分,达到受限的公共访问目的(c#在变量后接一个花括号等于引入了新的语法,没必要)。事实上lombok已经实现了看起来差不多的@Getter和@Setter修饰。
另外类继承和接口实现使用两个不同的关键字也很啰嗦,因为类只能继承,接口只能实现,共用一个关键字并不会产生任何语义方面的问题。比如——
class BlueCat : Cat, Pet {
}
这样就声明了一个BlueCat类,继承自Cat类且实现Pet接口,语义上完全不会有问题(但一些其他语言广泛的拓展冒号的语义则很混乱)。类似这样可以简化语法而不对语义产生负面影响的方面还有很多,有些其他语言的特性的确值得学习。
另一点抱怨则是我在记事本上把大体上的接口和结构定义好,重启到Linux下去做实现的时候,觉得很多地方实现起来很“咯手”。
因为对象其实是一种很死板的结构,你不能对一个对象在内存中的数据做任何的变形,仅仅将对象当做一种数据结构来看待的话,其实远不如c的结构体使用起来灵活。由于这一限制,一些时候需要把一个对象的成员变量赋到另一个对象上来完成结构体强转就能完成的事情,实际上在各种方面都不友好。
怀念起结构体来的同时还怀念起了函数指针。虽然JDK8带来的Lambda使回调写更容易了,但是比起c里面函数指针的方式还是差得很远。函数(或者说方法)本质上就是内存上的一段可执行区域,既然是内存在c里面当然可以用指针随便胡搞瞎搞。而Java则把细节给隐藏起来,方法成了一种很特殊的东西,完全与变量区别开来。即使是JDK8的Lambda也没有改变这一本质,回调只能传入接口或类的实例,因为方法是始终与对象绑定的。
public class Cat {
interface Moe {
void moe();
}
Moe moe;
void setMoe(Moe moe) {...}
void meo() { moe.moe(); }
static Cat newFatCat() {
return new Cat().setMoe(() -> {...});
}
}
而且Java存在的几个特性本质上就与函数指针有隔阂,抽象类和方法名重载。方法名重载决定了要在Java上重新实现函数指针也会是个很丑陋的东西,也会把原本对用户隐藏起来的方法签名给暴露出来。而抽象类带来的可实例化的类不允许存在未实现方法这一设定则封死了方法指针出现的余地。