Roman大神带你了解Kotlin如何实现自我进化

在这里插入图片描述
Kotlin团队的大牛Roman Relizarov在最近的一个演讲中,分享了Kotlin团队是如何收集、提炼用户需求、并最终落地成型的过程。其中举的几个case,都是呼声很高且有可能真正落地的语法,值得一看。
https://youtu.be/0FF19HJDqMo

YouTrack&KEEP


Kotlin团队通过YouTrack收集和跟踪来自开发者们的各种Issue,其中一些准入的Issue会进入KEEP进行管理。很多YouTrack的Issue初衷虽好,但以为不符合语言设计习惯等原因,经过不断讨论和演进,以一个最佳姿态落地成型。本文介绍的几个case也是经历了如此的演进过程,并有可能在未来的版本中出现


Namespace


KT-11968:有开发者提议通过Companion关键字,为Java类可扩展地定义静态方法/变量:

val android.content.Intent.Companion.SCHEME_SMS:String get() = "sms"

这样可以在Java中实现静态调用

Intent.SCHEME_SMS

这个本质上是一个对namespace的需求。Kotlin鼓励使用top-level function替代Util类,但有时我们希望提供类似namespace的机制方便我们索引这些方法,常见的做法是定义object类后充当静态方法使用:Delegates.notNull() ,这无形会增加一个obejct对象的创建,如果新增一个namespace关键字,则可以漂亮的解决类似问题

//KT-11968
val Delegates.Companion.notNull() = ... 

⬇️⬇️

//NOW
object Delegates {
    
                        
	fun <T : Any> notNull(): ...
	// other declarations
}

⬇️⬇️

//Maybe in FUTURE
namespace Delegates {
    
    
	fun <T : Any> notNull(): ...
	// other declarations
}

Multiple receivers


KT-10468:例如在Android中,一个方法需要借助View和Float两个receiver,此时希望定义多receiver的扩展方法

fun (View, Float).dp() = this * resources.displayMetrics.density
// explicitly: fun (View, Float).dp() = this@Float * [email protected]

class SomeView : View {
    
    
  val someDimension = 4f.dp()
}

现状我们是如何解决类似问题的呢?我们为了提供多个this上下文时,一般使用with()

with(view) {
    
    
	42f.dp()
}

with(...){ ... } 写起来嵌套过多,借鉴python等语言中,使用注解避免嵌套的的做法(decortor):

#python的decorator:

def hello(fn):
    def wrapper():
        print "hello, %s" % fn.__name__
        fn()
        print "goodby, %s" % fn.__name__
    return wrapper
  
@hello
def foo():
    print "i am foo"

因此是否可以结合注解decortor的方式,实现with(){}提供的receiver效果呢?

//KT-10468
fun (View, Float).dp() = this * resources.displayMetrics.density

⬇️⬇️

//NOW
with(view) {
    
    
	42f.dp()
}

⬇️⬇️

//Maybe in FUTURE
@with<View>
fun Float.dp() = this * resources.displayMetrics.density

Public/Private property types


KT-14663:声明一个属性时,同时出现Public和Private修饰符

private val items = mutableListOf<Item>()
        public get(): List<Item>
//or
val items = mutableListOf<Item>()
        get(): List<Item>

日常开发时,我们希望一个属性,对外是一个抽象类型,对内是一个具体类型,
现状做法是像下面这样,声明两个属性:

private val _items = mutableListOf<Item>()
val item : List<Item> by _items

由于这个Issue非常自然和容易理解,无需过多干预和改变,已经具备落地的条件


Value Class


我们常用 data class 来代表immutable的数据,并使用copy通过生成副本进行update,以避免修改原data,造成diff的失效。

// 1. 定义data class
data class State(
	val lastUpdate: Instant,
	val tags: List<String>
)

// 2. 通过copy进行update
state = state.copy(
	lastUpdate = now(),
	tag = state.tags + tag
)

// 3. 使用
notifyOnChange(state)

但是当嵌套过深时,copy方法使用起来就非常麻烦了。当然有人会说可以将成员定义成var,直接修改,但是这会造成后续diff的实效

// 1. 定义data class
data class State(
	var lastUpdate: Instant,
	var tags: List<String>
)

// 2. 直接update
state.lastUpdate = now()
state.tags += tag

// 3. copy后使用
notifyOnChange(state.copy) //此时如果后续有diff逻辑,会失效

此时我们试图设计一种新的类型Value Class,可以在update的同时生成副本,解决此类问题。

//val关键字定义class
val class State(
	val lastUpdate: Instant,
	val tags: List<String>
)

// update后,会产生副本
state.lastUpdate = now()
state.tags += tag

Summary


如果你喜欢Kotlin、关注并使用YouTrack、也许未来某个版本的Kotlin中就会出现你的想法。而你所做的贡献都会永久记录在YouTrack中。

猜你喜欢

转载自blog.csdn.net/vitaviva/article/details/109129600
今日推荐