详解Kotlin中如何实现类似Java或C#中的静态方法

大家可以在网络上搜到不少这样的文章,官方推荐是包级函数,也有人说用伴生对象(companion class)。这些都是不错的选择,但并不完善,我们在不同的情况下有更好的选择。我总结了几种方法,分别是:包级函数、伴生对象、扩展函数和对象声明。这需要大家根据不同的情况进行选择。

一、包级函数

Kotlin和Java及C#不同的是,可以在包里面直接声明函数。做法和类中是一样的,这里就不多说了,的确是一个非常好的选择。适用于函数不需要不包内部的类进行数据共享的方法。

二、伴生对象

从语义上来讲,伴生函数与Java中静态方法最为相近,所以用伴生对象完全可以实现Java中静态类的所有内容。但在Java中使用静态方法有时是没有办法的选择,在Kotlin中伴生对象只是我们的一种选择。下面我就介绍一下伴生对象。
大家在使用Java的时不知有没有注意到,Java类中的静态变量及方法是在什么时候初始化的?是在静态方法第一次调用时还是在相应的Java类被加载时?答案是在Java类被加载时(也就是说如果你调用过Java类中的实例变量及方法后,即使你没有使用静态变量及方法,静态变量已经初始化了)。这种现象用伴生来描述是不是很贴切。

在Kotlin中,认为一个类中有两类东东,一类是Java类中的实例变量及方法,另一类是Java类中的静态变量及方法。Kotlin将静态实例及方法统一打包到一个伴生类中,就是这个样子啦。下面给出一个例子:

fun main(args: Array<String>) {
 Books.getBestSellers()
}
class Books(var name: String, val page: Int) {
  fun getWordCount()=page*100
  companion object ComBooks{
    var bestSellers=arrayOf("Harry Potter\r\t","Lord of the Rings\r\t")
    fun getBestSellers() {
      bestSellers.forEach{v->println(v)}
    }
  }
}

伴生类是用companion来声明的,他在伴生对象所在的类被加载,伴生对象被初始化,与Java静态成员一样。其可以匿名或者与包含他的类类名相同。调用有两种: Books.ComBooks.getBestSellsers()?Books.getBestSellsers()?。

三、扩展函数

在Java中,我们经常用写Utils类,这些类往往都是针对某一个对象对其功能进行与自身程序相匹配的操作。其中的方法以静态方法居多,比方说:

public class Utils {

  public static boolean isEmpty(String string){
    return string != null && string.length() == 0;
  }

  public static boolean isWeakEmpty(String string){
    return isEmpty(string) && string.trim().length() == 0;
  }
}

我们当然可以用上面的两种方法来实现这些静态方法,但是我们有更好的方法。

fun String.isEmpty() = this != null && this.length == 0;

fun String.isWeakEmpty()= this.isEmpty() && this.trim().length == 0

上面两行代码给String这个类扩展了两个函数,这两个函数就可以像其原生函数一样调用,代码十分优美。其实扩展函数并没有修改String类内部的东东,也只是给String加了两个静态函数,但相比Java的Utils类,可读性有了非常大的提高。

四、对象声明

继续考虑上面的Utils类,这个类中所有的方法(有时也有可能有变量)都是静态的,这个方法根本没有必要实例化,在Java中我们经常将此种类声明为静态类,在Kotlin中针对这种情况有没有好的对应方案呢?有没有比伴生对象更好的方案呢?当然是有的,对象声明就是一种。

对象声明非常好理解,就是用object关键字声明了一个对象,对象里面可以用变量也可以有方法,如:

object AppInfo{
  var AppName = "Kotlin Message"
  var AppAuthor = "Riley Ge"
  fun toSimpleString() {
    println("AppName:$AppName,AppAuthor:$AppAuthor")
  }
}

发现Kotlin的对象真是强大!有一点大家注意一下,AppInfo是在第一次被访问到时延迟初始化的,也就是说在对象声明时AppInfo并没有初始化。

五、总结

说了这么多方法,现在没有人在担心Kotlin没有静态方法了吧,Kotlin没有只是因为他可以做的更好。而且Kotlin也给了大家更多的选择,大家可以根据自己的实际情况选用合适的方法,让自己的代码高效而优美。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Kotlin教程之基本数据类型

    Kotlin教程之基本数据类型的学习 基本类型 我们知道java的基本类型分为基本数据类型: int 普通整型 float 浮点型 char 字符型 short 短整型 byte 字节型 long 长整型 double 双精度 boolean 布尔型 和引用数据类型: class Type 类类型 interface Type 接口类型 array Type 数组类型 null Type 空类型 在 Kotlin 中,所有变量的成员方法和属性都是一个对象.一些类型是内建的,因为它们的实现是优化过

  • Kotlin 的注解类详解及实例

    Kotlin 的注解类详解及实例 注解声明 注解是将元数据附加到代码的方法.要声明注解,请将 annotation 修饰符放在类的前面: annotation class Fancy 注解的附加属性可以通过用元注解标注注解类来指定: @Target 指定可以用 该注解标注的元素的可能的类型(类.函数.属性.表达式等): @Retention 指定该注解是否 存储在编译后的 class 文件中,以及它在运行时能否通过反射可见 (默认都是 true): @Repeatable 允许 在单个元素上多次

  • Kotlin 封装万能SharedPreferences存取任何类型详解

    Kotlin 封装万能SharedPreferences存取任何类型详解 /** * author: smart * time: 2016/10/26 * 封装好SharedPreferences 并使用 序列化和反序列化来存储数据 * 注意要在全局环境使用 */ class Preference<T>(val context : Context,val name : String,val default : T) : ReadWriteProperty<Any?,T>{ val

  • Kotlin基础教程之伴生对象,getter,setter,内部,局部,匿名类,可变参数

    先来看一个名为Message的类 在这个类中有一段包含在companion object中的代码,需要说一下的是,Kotlin的class并不支持static变量,所以需要使用companion object来声明static变量,其实这个platformStatic变量也不是真正的static变量,而是一个伴生对象, 这个伴生对象位于Message类中定义的一个叫做Companion的内部类中,如图: 可以看到在Kotlin中编译器自动生成类是很常见的事情,那么这个伴生对象作何理解呢? 我的理

  • Kotlin基础教程之数据类型

    Kotlin基础教程之数据类型 一切都是对象. 在Kotlin中一切都是对象.Kotlin有一些基本类型Boolean,Byte,Shot,Int,Long,Float,Double 在Kotlin中没有原始类型,以上这些类型都是对象,比如 运行结果如下 Kotlin支持16进制字面值,二进制字面值和科学记数法,官方文档中没有提到8进制 所有基本的几个数据类型不会进行显式类型转换,这一点尤为重要!那么如何进行转换呢?如下: 可以使用toLong,toInt,toShort,toChar等函数进行

  • Kotlin 基础教程之类、对象、接口

    Kotlin 基础教程之类.对象.接口 Kotlin中类.接口相关概念与Java一样,包括类名.属性.方法.继承等,如下示例: interface A { fun bar() fun foo() { // 可选方法体 } } class Child: A { override fun bar() { // todo } override fun foo() { super.foo() } } class 构造器 Kotlin 中的类可以有一个 主构造器, 以及一个或多个次构造器, 主构造器是类头

  • kotlin基础教程之类和继承

    kotlin基础教程之类和继承 类声明 使用class关键字声明类,查看其声明格式: : modifiers ("class" | "interface") SimpleName typeParameters? primaryConstructor? (":" annotations delegationSpecifier{","})? typeConstraints (classBody? | enumClassBody)

  • Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket

    Kotlin基础教程之dataclass,objectclass,use函数,类扩展,socket Kotlin提供了一些机制来扩展已有的类,如下: 还记得我们之前写过的Point3D类吗?(将其略作修改,将成员变量改为Double类型) 让我们为其扩展一个length函数 扩展的方法很简单,只要在函数名前面加上类名就行了. 这样Point3D的对象就有了一个名为length的方法. 运行的结果不出所料: 除此之外,在Kotlin中还有一些特殊的类,比如Data Class: 有些类只包含数据,

  • 详解Kotlin中如何实现类似Java或C#中的静态方法

    大家可以在网络上搜到不少这样的文章,官方推荐是包级函数,也有人说用伴生对象(companion class).这些都是不错的选择,但并不完善,我们在不同的情况下有更好的选择.我总结了几种方法,分别是:包级函数.伴生对象.扩展函数和对象声明.这需要大家根据不同的情况进行选择. 一.包级函数 Kotlin和Java及C#不同的是,可以在包里面直接声明函数.做法和类中是一样的,这里就不多说了,的确是一个非常好的选择.适用于函数不需要不包内部的类进行数据共享的方法. 二.伴生对象 从语义上来讲,伴生函数

  • 详解Kotlin中的面向对象(二)

    详解Kotlin中的面向对象(二) 在Kotlin中的面向对象(一)中,介绍了Kotlin类的相关操作,本文将在上文的基础上,继续介绍属性.接口等同样重要的面向对象的功能. 属性 class AttrDemo{ private var attr1 : String = ""; protected var attr2 : String = ""; public var attr3 : String = ""; var varattr : Strin

  • 详解Kotlin中的变量和方法

    详解Kotlin中的变量和方法 变量 Kotlin 有两个关键字定义变量:var 和 val, 变量的类型在后面. var 定义的是可变变量,变量可以被重复赋值.val 定义的是只读变量,相当于java的final变量. 变量的类型,如果可以根据赋值推测,可以省略. var name: String = "jason" name = "jame" val max = 10 常量 Java 定义常量用关键字 static final, Kotlin 没有static,

  • 详解Kotlin Android开发中的环境配置

    详解Kotlin Android开发中的环境配置 在Android Studio上面进行安装插件 在Settings ->Plugins ->Browse repositores.. ->kotlin 安装完成后重启Android Studio就生效了 如图所示: 在Android Studio中做Kotlin相关配置 (1)在根目录 的build.gradle中进行配置使用,代码如下: buildscript { ext.kotlin_version = '1.1.2-4' repos

  • Java 添加、删除、格式化Word中的图片步骤详解( 基于Spire.Cloud.SDK for Java )

    本文介绍使用Spire.Cloud.SDK for Java提供的ImagesApi接口来操作Word中的图片.具体可通过addImage()方法添加图片.deleteImage()方法删除图片.updateImageFormat()格式化Word中的图片以及getImageFormat()获取Word中的图片格式等.操作方法和代码示例可参考下文中的步骤. 步骤1:导入jar文件 创建Maven项目程序,通过maven仓库下载导入.以IDEA为例,新建Maven项目,在pom.xml文件中配置m

  • 详解UDP协议格式及在java中的使用

    UDP是面向无连接的通讯协议,由于通讯不需要连接,所以可以实现广播发送.UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出现丢包现象,实际应用中要求程序员编程验证. UDP适用于DNS.视频音频等多媒体通信.广播通信(广播.多播).例如我们常用的QQ,就是一个以UDP为主,TCP为辅的通讯协议. UDP报文格式如下: UDP首部有8个字节,由4个字段构成,每个字段都是两个字节, 源端口:数据发送方的端口号. 目的端口:数据接收方的端口号. 长度:UDP数据报的整个长度(包括首部和数据),其

  • 详解 Kotlin Reference Basic Types, String, Array and Imports

    详解 Kotlin Reference  Basic Types, String, Array and Imports 基本数据类型 Kotlin中支持的基本数据类型及它所占Bit宽度: Type Bit width Double 64 Float 32 Long 64 Int 32 Short 16 Byte 8 Char 在kotlin中 并不是一个数值类型 kotlin不支持8进制, 支持 2.10.16进制 下面的代码,示例了: 关于2.10.16进制: 使用下划线在数值常量赋值数据中:

  • 详解 Kotlin Reference  Basic Types, String, Array and Imports

    详解 Kotlin Reference  Basic Types, String, Array and Imports 基本数据类型 Kotlin中支持的基本数据类型及它所占Bit宽度: Type Bit width Double 64 Float 32 Long 64 Int 32 Short 16 Byte 8 Char 在kotlin中 并不是一个数值类型 kotlin不支持8进制, 支持 2.10.16进制 下面的代码,示例了: 关于2.10.16进制: 使用下划线在数值常量赋值数据中:

  • 详解Kotlin 高阶函数 与 Lambda 表达式

    详解Kotlin 高阶函数 与 Lambda 表达式 高阶函数(higher-order function)是一种特殊的函数, 它接受函数作为参数, 或者返回一个函数. 这种函数的一个很好的例子就是 lock() 函数, 它的参数是一个锁对象(lock object), 以及另一个函数, 它首先获取锁, 运行对象函数, 然后再释放锁: fun <T> lock(lock: Lock, body: () -> T): T { lock.lock() try { return body()

  • 详解Kotlin的空指针处理

    详解Kotlin的空指针处理 Kotlin的空指针处理相比于java有着极大的提高,可以说是不用担心出现NullPointerException的错误,kotlin对于对象为null的情况有严格的界定,编码的阶段就需要用代码表明引用是否可以为null,为null的情况需要强制性的判断处理. 咋看一下这些在java里面其实也有,问题是一般开发中不写也是可以的(大部分开发不会花很多时间考虑这些),等出了空指针错误再一个个打补丁.这样往往会遗漏很多空指针,后期的解决仅仅是做一个if判断,没有从根源解决

随机推荐