Kotlin 的 Any

今天,我们来看看 Kotlin 里的 Any,它相当于 Java 里的 Object,所有其他的类都默认继承了它。Kotlin 比 Java 的面向对象更彻底, Java 还有基础类型,它们没有继承 Object, Java 的方法也不是对象,而 Kotlin 的方法是对象。

Any 的构造函数就不多说,就是能构造出它的对象,

Any 的函数

  1. equals
  2. hashCode, 唯一标示这个对象
  3. toString

这三个函数跟 Object 里的相同,这里不再详述

Any 的扩展属性

javaClass 代表一个对象的运行时 java class(当然只在 JVM 上有这个属性)

1
val <T : Any> T.javaClass: Class<T>

这个写法还是需要解释一下的,首先,扩展函数的定义形式是这样的,例如:

1
2
3
4
val String.wordsCount: Int
get() {
...
}

而上面 javaClass 的定义,用到了类型参数,我想说,这真的是太牛逼了,类型参数,指定每个所有继承 Any 的 T 都有 javaClass 这个属性,并且 javaClass 得到的是 T 这个类的 java 运行时 class

扩展函数

also

1
fun <T> T.also(block: (T) -> Unit): T

also 会接受一个代码块,这个代码块以 this 为参数,并且返回 this。

扩展函数跟扩展属性同样使用了类型参数,不过,这样算是 Any 的扩展函数吗? 当然,一切解释权归官方所有,官方认为是就是了。

我们知道了扩展函数的好处,扩展函数可以使用类型参数作为 Receiver,从而在子类上调用该扩展函数时,我们拿到的 Receiver 是子类。

also 和 apply

1
fun <T> T.apply(block: T.() -> Unit): T

also 和 apply 的作用可以说是完全一样,它们都可以执行一个代码块,并且返回 Receiver。但是它们有区别的,传入 also 的代码块,将 Receiver 作为参数,而 apply 将 apply 的 Receiver 作为代码块的 Receiver。文字还是太苍白,让我们举个栗子:

1
2
3
4
5
6
7
8
9
val john = Person().apply {
wearHat()
wearCoat()
}

val lili = Person().also {
it.wearHat()
it.wearCoat()
}

这样就清晰明了了,also 将自己的 Receiver 作为代码块的参数,而当代码块但参数时,可以不写出来,默认这个参数的名字叫 it

对于我来说,它们在语意上,apply 的代码块内更像过程编程,描述一些有顺序的行为,而 also 的代码块内更像面向对象,给这个 it 发信息,设置一些状态。

let 和 run

1
2
3
fun <T, R> T.let(block: (T) -> R): R

fun <T, R> T.run(block: T.() -> R): R

let/run 的差别 跟 also/apply 的差别相同,还是再说一遍,let 将自己的 Receiver 作为 代码块的参数 而 run 将自己的 Receiver 作为代码块的 Receiver。let/run 与 also/apply 的区别在于返回值, 之前提到,also/apply 的返回值是它们的 Receiver,而 let/run 的返回值是代码块表达式的最后返回值。

1
2
3
4
5
6
7
8
9
10
11
val result1 = Calculator().run {
addOne(23)
addAnother(43)
compute()
}

val result2 = Calculator().let {
it.addOne(23)
it.addAnother(53)
it.compute()
}

我发现在语言表达上,它们两个也还是有区别的,run 同 apply 运行一些指令,有顺序的运行。而 let 让它做一些动作,最后,获取一个结果

takeIf 和 takeUnless

1
2
3
fun <T> T.takeIf(predicate: (T) -> Boolean): T?

fun <T> T.takeUnless(predicate: (T) -> Boolean): T?

这两个扩展函数都是 kotlin 1.1 版本添。它们都会接受一个断言,在断言返回 true 时 takeIf 返回自己,否则 返回 null;takeUnless 与之相反,在断言返回 false 时返回自己,在断言返回 true 时返回 null。上代码:

1
2
3
val index = "Kotlin".indexOf('K').takeIf { it > 0 } ?: 0

val personName = person?.Name ?: "no name"

这个例子里将 takeIf 与 ?. 做了对比,它们都提供了一个默认值的形式。只不过 takeIf/taskUnless 更普遍,可以自己定义条件来决定是否使用默认值。

to

1
infix fun <A, B> A.to(that: B): Pair<A, B>

to 比较有趣,它是一个中缀运算符,也就是类似这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
val person1 = Person().run {
wearHat()
wearCoat()
name to this
}

val person2 = Person().let {
it.wearHat()
it.wearCoat()
it.name to it
}

val person = mapOf(person1, person2)

我们可以看到,我们在 run/let 分别使用 to 构造了两个 Pair,而 Pair 正好可以作为 map 的键值对,于是我们构造了一个包含两个人的 map。

toString

1
fun Any?.toString(): String

这个 toString 是一个扩展函数,它并没有比之前那个 toString() 函数高级多少,只是 Receiver 是 Any? 也就是在 Receiver 为 null 的时候也会调用 toString()。

1
val name = person.toString()

我们不管 person 到底是不是 null 了。还是为了解决 Java 中的 NullPointerException 的问题。


还有几个 JavaScript 相关的扩展函数,我们这里没有列出来,如果需要请自行查看。类似了。

被逼死的程序员

最近一个引起媒体关注的事件是一个程序员被前妻逼死。这个程序员是个 IOS 开发者,做了一个应用,收入不少,他开了公司,这个前妻,向他要钱,恐吓,最终导致这个程序员无路可走,只得自杀。

我一向不喜欢凑热闹的,但是这几天我憋得不行,我不想说那女的有多坏,多可恶,并不是说我接受了这种事情,见怪不怪了,而是这个程序员的自杀,让我再一次认识到,人的思想的差距有多大。

尽管我不知道,死亡多么的可怕,死后会怎样,但是,一个正常的人很难去自杀的,因为人类长久的进化,将那些不畏死亡想死亡的基因一次一次的筛选,这时间如此长,筛选次数如此之多,应该让人类完全没有这中想法才对。当然,我也听说过,其他一些自杀的,但是更多听说的是,有些人有心理疾病,他们会自虐,自虐这种基因会流传下来,因为自虐并不会死亡,而只有死亡是筛选边界。

今天看了一个视频,是台湾的一个重症专家,他说他很适合谈生死,因为他看了太多的死亡。他的一个观点让我印象深刻,人生的意义是什么呢? 他说,追寻这个问题的答案就是这个问题的答案。说的很绕口,意思是人生是一个过程,而这个过程里,不断去思考一个问题。

这个被逼死的程序员让我很痛苦,哀其不幸,怒其不争。那个女人恐吓他偷税扣税,灰色收入,为什么不去自首坦白,这一切最坏的结果,没收全部资产,蹲监狱几年,出来依然一条好汉。难道舍不得钱?

不去揣测其中的原因,我们还是应该去追求那个问题的答案,人生的意义到底是什么?如果一个人如果不想活了,多半是他找到。

对语法糖的看法

Kotlin 是一门实践导向的语言,什么意思呢,就是他就是想让程序员用的更爽。所以他用了很多语法糖,来去除一个模板代码,模板代码应该就算是一门语言的习语吧。不如在 Java 里要写个单例,那都需要一下几步:

  1. 将构造函数私有化,不让使用者自己随便创建对象
  2. 在该类内定义一个私有的静态属性,类型为该类
  3. 提供一个公有的静态 getInstance() 方法, 在第一次使用的时候初始化之前那个私有静态属性,并返回,之后就可以不在初始化了,直接使用那个对象就行。

以上的过程,在代码中是经常出现的,还有几种初始化的方法,我们总选一种比较好的。而在 Kotlin 内,只需要使用 object 关键字修饰 class。

还是来个栗子吧

Java 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Singleton {
private volatile static Singleton singleton; // 2
private Singleton (){} // 1
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

Kotlin 代码:

1
2
object Singleton {
}

这个对比,可为震撼?

有些拿语法糖说事,最早我知道语法糖好像是一篇写 Python 的文章,说 Python 有很多语法糖,我很难认同,感觉这就是酸葡萄心理,这个写文章的不是 C 语言开发者,就是 Java 语言开发者。

大部分对语法糖的指责是它没有给语言添加什么功能,只是对原有语言的封装,可是这有什么呢,原来的语言已经完备了,何必添加功能。语言是人类与机器之间的交流的工具,我们要发着这个工具,添加一些常用语,这是多么好呀,比如我们的缩略语 WTF,lol等等。

当然,一些编程初学者并不建议学习 Kotlin, 可以先学习 Java 在学习 Kotlin。

下一篇,我会翻译一下 Kotlin 官网对 Kotlin 习语的整理。

<翻译> Java VS Kotlin

要想了解一个新事物,将它与所熟悉的就实物做对比是最好不过的方式了,下文为 Kotlin 官方网站的一篇文章,对 Java 和 Kotlin 做了对比。我根据自己的理解添加了一点解释。原文对每一条都有链接让你去深入了解,很好!!

Java 有, Kotlin 没有的:

  1. checked 异常(一个方法在声明抛出异常后,使用它的方法必须使用 try 捕获或者声明抛出)
  2. 基本类型,它们不是类
  3. 静态方法,属于类的方法
  4. 非私有 Feild(Java 的类包含数据和方法,数据被称为 Feild,可以直接在外部访问非私有的Feild)
  5. 泛型里的通配符(类似这种的 Collection<? extends E> 或者这样 List<? super String>)

Kotlin 有, Java 没有的:

  1. lambda表达式 和 内联函数(能够提高性能)
  2. 扩展函数
  3. Null 安全(变量区分可Null 和 可不Null)
  4. 智能转换
  5. String 模板(类似这样的 println(“hello $Name”))
  6. 属性(准确的说,Java里面的类的数据叫 Feild)
  7. 基本构造器(类似这样的 class Persion(name: String) {} 这里的小括号是基本构造器)
  8. 支持代理模式,不需要写多余的代码(类似这样的 class Proxy(impl: Base): Base by impl)
  9. 变量和属性的类型推断 (val a = 5, 可以推断出 a 的类型是 Integer,并不是动态类型)
  10. 支持单例模式 (类似这样的 object Global {})
  11. 类型参数(类似 Java 的反省)
  12. 区间表达式 (类似这样的 1..5 == [1, 2, 3, 4, 5])
  13. 操作符重载 (可以重新定义 + - 等等)
  14. 伙伴对象 (Companion Object, 可以用来实现静态变量,静态方法)
  15. 数据类 (类似这样 data class Persion(name: String) {} 就是在正常的类之前加了个 data Kotlin 会给太生成一些方法)
  16. 区分了可变集合和不可变集合
  17. 协程 (不是说走就走的那个携程)

原文(Comparison to Java Programming Language)

生活中学习编程

控制

适当的时候放下, 需要的时候拿起

琐事

有时候我们买了很多东西回家,走到门口,需要开门,这时候手里拿着东西,就懒得放下,于是费劲的伸手到口袋拿钥匙,然后费劲的挑起胳膊上的重物去插钥匙,整个过程,十分艰难。可是开个钥匙有这么艰难吗?

如果有人跟我说他开钥匙累的不行,我会想,你的钥匙需要润滑了。开个钥匙就是简单的呀。

问题出在没有把手里的东西放下。有时候是因为不自知,根本没意识到,有时候是因为怕麻烦。

还是想象一下,开个钥匙是多么简单,即使是从超市买了大量的东西。来到门前,把东西放下,从口袋拿出钥匙,插入锁孔,一拧就开了。放下东西,拿起东西,这也不会浪费多少时间,费多少事。

有时候我们就是太追求达到目的,不愿有一点弯路,然而,路程的增长可能换来很多,比如更轻松,更安全。

编程

将这个感悟应用到编程,就是多写点代码,多加个方法,多加个类,可能会让代码逻辑更清晰,虽然有那个理论: 代码越多,bug越多。

有时候,我们就是想一门心思把代码写完,把问题解决,于是,忘记了步步为营,越走越快,不写注释,不将代码抽象出方法,从而让自己工作记忆饱和,影响了控制能力。

背诵课文

有很多事,我们曾经就那么不知道所以然的做了,而且做的很痛苦。上学时候的背课文就是这种事情。

那时候,背课文的目的就是要背过,能够在考试让背诵的时候背诵下来,考试的时候能够填写缺钱的词句。然而现在想来,能记住些什么呢?

我记得《锄禾》

锄禾日当午,
汗滴禾下土。
谁知盘中餐,
粒粒皆辛苦。

有什么用,想来其实还是有点用的,首先小孩子都会,你不会感觉很丢脸。我们,知道每句诗的意思,在背诵的过程中,尽管我们没有可以的去理解其中的思想,我们也能被潜移默化。

上面我们提到,背诵会潜移默化的影响我们,更精确一点,实际上是在一遍一遍的阅读中,回顾中,我们看到了它所包含的各个点。

我认为,背诵的效用并不在于背过,而是在于在一遍一遍的重复中,我们的注意力会变化。以上面的《锄禾》为例,最开始的时候,我们可能需要先认识字,能读下来,这会用几遍阅读,然后,我们理解了每个字的意思,每一句的意思,接下来,我们可能会注意到这是个五言诗,一三四句的韵脚是u。在读的遍数多了,我们可能就会想这首诗在什么时候会用到了。比如在大太阳地下拔草时,比如看到小孩子剩了几粒米饭时………

我们在不断的重复中,注意力在不断的变换,与其他知识产生更多的联系,这正是那句古人云: 读书百变,其义自见。只不过,去过我们真读百遍,我们得到的可能不仅仅那本书所表达的意思,可能更多的多。这有点像格物,就是对着一个东西反复思考。

然而,我们当年的背诵课文,有些明确的目的,而且很单纯,就是背诵过,可能还会多一点,就是理解透,我觉得这样不如细细品味一百遍收获多。


说说总是容易,有本事我们反复做上一百遍试试?我又想定计划了

睡前吃了个桃子

前天,睡前吃了个桃子,然后刷了牙就睡觉了,然后第二天醒来,感觉嘴里就有桃子的味道,啊,不要恶心,听我慢慢道来。这让我想到羊的反刍(fan chu 竟然年反除, 我打了老半天fan zou都没找到),反刍就是羊这类动物,它们吃下东西去,在胃里消化消化,有返回嘴里,再咀嚼。当然,我们有这功能,但是根据我晚上吃西瓜的经验,好像真的会在睡觉的时候往上反西瓜水,所以我真心不敢睡前吃太多西瓜。当然这并不是太重要,因为如果西瓜会反刍,那我不吃就是了,可是,会不会,其他的食物,在睡眠中也会呢,这是不是就是我的牙坏的快的原因呢。

一直以来, 对于我的蛀牙,我家人都认为我是小时后吃糖吃的,但是,我一直以为自己的牙之所以不好,是因为我的口腔环境的问题,这属于个人身体状态的问题,而不是什么吃糖多的问题,就算是我小时候吃糖多,也不可能影响到现在,会永久改变我的口腔环境。牙齿蛀牙多有很多的原因,比如喝的水呀,吃的东西呀,当然都应该是一些长期使用的物品。不刷牙当然是一个很重要的原因,我只在夜晚睡前刷,因为如果不刷,早上起来感觉嘴里产生大量的反应物质不知道是什么东西。

我想整牙,但是,我就是不去做,真是蛋疼,甚至连补牙,我都懒得去做,哎,做人真是忧伤。如果是条狗,想吃就吃,想要就要。


这个蛋扯得稀巴烂

我们都到了结婚的年纪

今天晚上,又回来到很晚,我的一个小学同学打来电话,跟我聊天,一个女生,大谈年纪大了,该结婚了。

我跟她真的是从小学,中学,大学,工作了,都有点练习的那种,我非常了解她,我不能了解女生,但是我了解她,特别的好强,我又时候想起来会疼心疼,曾经初中的时候暗恋她,上厕所的路上看这看那,希望能看见她。我从初一年纪就转移了暗恋对象,而这一暗恋,就是七年之久,说来好像还有点自豪的感觉,真他妈蛋疼。

这么多年过去了,我们就只是偶尔联系一下,上次去上海,跟她聊了聊,这不,大概又一年了,又聊了聊,但每次都感觉很熟悉,真的,说到这,还真没有其他女生有这种感觉。真的是相亲人,说到这,甚至都没有某个其他人像他一样,就像是我的一个姐妹。实际上,我在小学初中,都曾幻想它是我的一个姐姐,因为,我听我妈说,我有个姐姐在生下来夭折了,是,我还是挺能胡思乱想的:扔在了家北的坡里,被人捡走了,养大成人。于是小学的时候,我们像冤家,都是一样的孤僻,不合群,时而关系好时而关系坏,但从来没有打起来过,她可是男生女生的都打过。

我一直都对她又爱又恨,爱的恨的也都是她的好强的性格,不服输,她长得挺漂亮,身材也好,在初中扔标枪冠军,跑步也很厉害,学了很多东西,耽误了成绩,后来学习了音乐,上了大学,反正是个多面能手,表现型的人,都不会差,但是还要看能不能承受自己给自己的压力,我知道她承受了太多的压力,都是自己加个自己的。在我看来完全不必要,想来,我也让自己很痛苦,但实际不同,我这痛苦根本不算什么,比如我我今天如果没写文章,我感觉好蛋疼呀。但是她可能会真的捶胸顿足,跟自己生气,急。

二十七八九,真的是到了该结婚的日子,可是我们能着急吗?关键是着急有用吗?


心声很难表达呀,只愿那些我爱的人,都能好好的。
大爱无疆的我又回来了

再谈身体状态

我感觉身体不知道从什么时候被掏空,就没有再满血过,今年体检要开始了,我要去好好体检一下了【哭笑不得】。

我想努力去描绘一下我现在的状态,应该有一个月了吧,那是夏天刚刚过去的日子,天转凉的时候,我就感觉头脑发涨,也不是感冒,好吧,是不是感冒我不确定,反正我没吃药,而且我记得,每年夏天转秋天的时候,我都会出现这种状态。

对于季节性的出现某种状态,我是深信不疑的。因为我曾经手上吐露皮,每年都会在某个季节蜕皮,所以我的手一直都是小鲜肉,虽然其他身体部位已经不是了。既然说到这,我想起一个特别神器的现象,就是曾经我手上涨了两个“猴子”,倒是不疼,但是挺难看的,于是我经常掐它,但是好几年,它都在那。但是,某一天,我突然意识到一个”猴子”没了,然后现在我意识到,另一个”猴子”也没了。这可真是神奇,当然这种感觉神奇的时候,我有感觉到自己的无知。一定有医学上的解释。

接着回来说我的现在的不良状态,在这个换机的不良状态,一段时间后,头不怎么疼了,但是身体依然感觉无力,上上周去爬山,回来就更加感觉身体虚,然后最近虽然稍有起色,但是脑筋又有点迟钝。

我想说的是,尽管这么长时间不在状态,但是我一直可以顺当的完成工作任务,但是,这周,前两天几乎没怎么有产出,啊,今天晚上有产出了,算是补了两天的工作。我在那看着代码,看哪哪不顺眼,一坨翔一样的东西,怎么都下不了手去改,最后,就在晚上吃完晚饭吧,吭哧就有了行动的能力,狂吃狂吃删代码,狂吃狂吃改代码,最终,有了一点不大不小的成果,但是任务已然已经拖延了。

其实之前也有过这种时候,就是排期下来后,前一段时间,下不了手,最后迫在眉睫了,吭哧吭哧高效率完成。呀,怎么这节奏这么熟悉,真他妈不是拖延症吗?要这么说,我肯定的了拖延癌症了,没救了。


哎,生活之苦在于,不吃饭饿的慌,吃了饭撑得慌

男士对女士的审美关注点

写在前面

这篇文章的闪念胶囊已经在手机上一周多了吧,昨天想写的,但写了另一个,今天跟颜同学聊天,聊到这,正好提醒了我。不过说实话,这个还是有点敏感的,如果有某个女士看到了,希望理解,我只是说说自己的想法,并尝试看到其中的真实性,没有一丝恶意。

对于美,我们总是不会排斥的,而对于美女,男士更是趋之若鹜,没有不喜欢的,这不在乎性,我们只谈美。

赤裸裸的说,男士对女士的审美关注点,是从上到下移动的。

在一项研究中,英国埃克塞特大学的研究人员选择了一系列女人头像的照片,让成年人根据这些头像的美丑程度打1~5分,然后把得分最高和最低的照片一对一对地编成一组,每组照片除了美丑程度不同,其他方面(例如亮度、对比度)都相似。再把它们拿给出生1~7天的新生儿看。一个研究者拿着两张照片放在距离新生儿眼睛大约30厘米的地方,另一个研究者在旁边观察。结果发现,几乎所有新生儿都花更多的时间去看美女头像照片。

这就标明,喜欢美女,分辨美女,是天生的。但我想说的是,这时候应该都是看脸吧。

然后,随着年龄的增长,到了青春期,成年,有些人的关注点开始移动了。男士们开始关注女士的胸部。其实关注胸部这是有进化原因的,女士的胸部是用来哺育下一代的,而到了成人,进化选择了那些想要哺育下一代的,而这些男士肯定回去寻找能更好的哺育下一代的女士。说到进化,在进一步,还有很多男士喜欢女士的臀部,这同样也是出于对下一代的考虑,看臀部就能知道女士能不能顺利的产下下一代。当然这些在现代都是没有价值的了,因为养孩子不在需要奶水,生孩子也不再需要顺产。但是这些自然选择留下来的本能,还将一直存在下去。

再往下,就是大长腿,其实这时候,关注的是整个身材,感觉像是个更高级的追求,是人类才有的。

再往下呢,有个恋脚癖,这都成病了,变态了,说到变态就太多了,我还是即使刹车吧。不过在古代,三寸金莲,这对脚的审美还是很普遍的。


最近老想写点科普的文章,但是发现知识浅薄的可以斗量,唯有学习学习再学习。
还是想表一下决心,写的很烂,但是表达了我的所思所想,我不怕烂。