常用到的几个Kotlin开发技巧,减少对业务层代码的入侵

我正在参加「掘金·启航计划」

本篇文章主要介绍常用到的几个kotlin开发技巧,能够帮助我们减少对业务层代码的修改,以及减少模板代码的编写。

善用@get/@set: JvmName()注解并搭配setter/getter使用

假设当前存在下面三个类代码:

#Opt1

public class Opt1 {
private String mContent;
public String getRealContent() {
return mContent;
}
public void setContent(String mContent) {
this.mContent = mContent;
}
}
public class Opt1 {



    private String mContent;

    public String getRealContent() {
        return mContent;
    }

    public void setContent(String mContent) {
        this.mContent = mContent;
    }
}
public class Opt1 { private String mContent; public String getRealContent() { return mContent; } public void setContent(String mContent) { this.mContent = mContent; } }

#Opt2

public class Opt2 {
public void opt2(Opt1 opt1) {
System.out.println(opt1.getRealContent());
}
}
public class Opt2 {



    public void opt2(Opt1 opt1) {
        System.out.println(opt1.getRealContent());

    }

} 
public class Opt2 { public void opt2(Opt1 opt1) { System.out.println(opt1.getRealContent()); } }

@Opt3

public class Opt3 {
public void opt3(Opt1 opt1) {
System.out.println(opt1.getRealContent());
}
}
public class Opt3 {



    public void opt3(Opt1 opt1) {
        System.out.println(opt1.getRealContent());

    }

}
public class Opt3 { public void opt3(Opt1 opt1) { System.out.println(opt1.getRealContent()); } }

这个时候我想将Opt1类重构成kotlin,我们先看下通过AS的命令Convert Java File to Kotlin File自动转换的结果:

image.png

可以看到为了兼容Opt2Opt3的调用,直接把我的属性名给改成了realContent,kotlin会自动生成getRealContent()setRealContent()方法,这样Opt2Opt3就不用进行任何调整了,kotlin这样就显得太过于智能了。

这样看起来没啥问题,但是java重构kotlin,直接把属性名给我改了,并隐式生成了属性的set和get方法,对于java而言不使用的方法会报灰提示或者只有当前类使用AS会警告可以声明成private,但是对于kotlin生成的set、get方法是隐式的,容易忽略。

所以大家在使用Convert Java File to Kotlin File命令将java重构kotlin的结果一定不能抱有百分之百的信任,即使它很智能,但还是一定要细细的看下转换后的代码逻辑,可能还有不少的优化空间。

这个地方就得需要我们手动进行修改了,比如不想对外暴露修改这个字段的set方法,调整如下:

class Opt1 {
var realContent: String? = null
private set
}
class Opt1 {

    var realContent: String? = null
        private set
}
class Opt1 { var realContent: String? = null private set }

再比如保持原有的字段名mContent,不能被改为realContent,同时又要保证兼容Opt2Opt3类的调用不能报错,且尽量避免去修改里面的代码,我们就可以做如下调整:

class Opt1 {
@get: JvmName("getRealContent")
var mContent: String? = null
private set
}
class Opt1 {

    @get: JvmName("getRealContent")
    var mContent: String? = null
        private set
}  
class Opt1 { @get: JvmName("getRealContent") var mContent: String? = null private set }

善用默认参数+@JvmOverloads减少模板代码编写

假设当前Opt1有下面的方法:

public String getSqlCmd(String table) {
return "select * from " + table;
}
public String getSqlCmd(String table) {
    return "select * from " + table;
}
public String getSqlCmd(String table) { return "select * from " + table; }

且被Opt2Opt3进行了调用,这个时候如果有另一个类Opt3想要调用这个函数并只想从数据库查询指定字段,如果用java实现有两种方式:

  1. 直接在getSqlCmd()方法中添加一个查询字段参数,如果传入的值为null,就查询所有的字段,否则就查询指定字段:
public String getSqlCmd(String table, String name) {
if (TextUtils.isEmpty(name)) {
return "select * from " + table;
}
return "select " + name + " from " + table;
}
public String getSqlCmd(String table, String name) {
    if (TextUtils.isEmpty(name)) {
        return "select * from " + table;
    }
    return "select " + name + " from " + table;
}
public String getSqlCmd(String table, String name) { if (TextUtils.isEmpty(name)) { return "select * from " + table; } return "select " + name + " from " + table; }

这样一来,是不是原本Opt2Opt3getSqlCmd()方法调用是不是需要改动,多传一个参数给方法,而在日常的项目开发中,有可能这个getSqlCmd()被几十个地方调用,难道你一个个的改过去?不太现实且是一种非常糟糕的实现。

  1. 直接在Opt1中新增一个getSqlCmd()的重载方法,传入指定的字段去查询:
public String getSqlCmd(String table,String name) {
return "select " + name + " from " + table;
}
public String getSqlCmd(String table,String name) {
    return "select " + name + " from " + table;
}
public String getSqlCmd(String table,String name) { return "select " + name + " from " + table; }

这样做的好处就是不用调整Opt2Opt3getSqlCmd(String table)方法调用逻辑,但是会编写很多模板代码,尤其是getSqlCmd()这个方法体可能七八十行的情况下。

如果Opt1类代码减少即200-400行且不负责的情况下,我们可以将其重构成kotlin,借助于默认参数来实现方法功能增加又不用编写模板代码的效果(如果你的Java类上千行又很复杂,请谨慎转换成kotlin使用下面这种方式)。

@JvmOverloads
fun getSqlCmd(table: String, name: String? = null): String {
return "select ${if (name.isNullOrEmpty()) "*" else name} from $table"
}
@JvmOverloads
fun getSqlCmd(table: String, name: String? = null): String {
    return "select ${if (name.isNullOrEmpty()) "*" else name} from $table"
}
@JvmOverloads fun getSqlCmd(table: String, name: String? = null): String { return "select ${if (name.isNullOrEmpty()) "*" else name} from $table" }

添加默认参数name时还要添加@JvmOverloads注解,这样是为了保证java只传一个table参数也能正常调用。

通过上面这种方式,我们就能保证实现了方法功能增加,又不用改动Opt2Opt3对于getSqlCmd()方法的调用逻辑,并且还不用编写额外的模板代码,一举多得。

总结

本篇文章主要介绍了在java重构成kotlin过程中比较常用到的两个技巧,最终实现效果是减少对业务逻辑代码的入侵,希望能对你有所帮助。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYgbxZEX' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片