当前位置: 首页 > news >正文

toString

有时候我们需要以字符串的形式提交信息,例如在调试时输出到控制台。那么,如何将非文本对象表示为可读字符串呢?这就需要用到 toString() 函数。


引言

假设我们有三个盒子,分别装有不同种类的浆果:覆盆子(raspberry)草莓(strawberry)蓝莓(blueberry)。我们需要这些盒子的重量信息,并打印出来:

val raspberryWeight = 10
val strawberryWeight = 15
val blueberryWeight = 20println(raspberryWeight) // 10
println(strawberryWeight) // 15
println(blueberryWeight) // 20

解释代码:
这看起来没问题。我们定义了三个变量,存储每种浆果的重量,并通过 println() 输出了它们。

现在我们定义一个 BerryHolder 类,用来存储这些盒子的重量,并再次尝试打印这些值:

class BerryHolder(val weight: Int)val raspberryWeight = BerryHolder(10)
val strawberryWeight = BerryHolder(15)
val blueberryWeight = BerryHolder(20)println(raspberryWeight) // BerryHolder@6f496d9f
println(strawberryWeight) // BerryHolder@723279cf
println(blueberryWeight) // BerryHolder@10f87f48

解释代码:
这次的结果看起来就不太理想了,输出的并不是我们期望看到的重量,而是类名和内存地址。


为什么会这样?

要理解这一点,我们需要知道 println(message: Any?) 是怎么工作的。它的参数类型是 Any?,这意味着 Kotlin 中的所有类(标准类或自定义类)都可以传递进去。
由于 println() 要处理任意类型的对象并将其输出为字符串,所以它会隐式地调用对象的 toString() 函数


默认行为

toString() 函数定义在 Any 类中,这是所有类的父类。因此,任何类都继承了 toString() 方法。

但默认的 toString() 实现,返回的是类名 + 内存地址的字符串。

对于一些内置类型,比如 IntDoubletoString() 方法已被重写以提供更有意义的输出:

val nonString = 1.0println(nonString.toString())   // 1.0
println(nonString)              // 1.0

解释代码:
上面两种写法效果相同,println() 隐式调用了 Double 类型的 toString()

但对于大多数类,如果没有特别重写 toString(),仍然会输出类名+内存地址。


重写 toString()

为了让我们的类输出有意义的字符串内容,我们需要重写 toString() 方法。比如:

class BerryHolder(val weight: Int) {override fun toString(): String {return weight.toString()}
}
println(BerryHolder(10)) // 10

解释代码:
现在,我们创建的 BerryHolder 对象在被打印时会输出它的重量,而不是内存地址。


更复杂的例子

现在我们要开发一个电子图书馆系统,其中有一个 User 类,包含用户的 ID、登录名和邮箱。

我们希望输出格式类似于:
User{id=id_value, login=login_value, email=email_value}

class User(val id: Int, val login: String, val email: String) {override fun toString(): String {return "User{id=$id, login=$login, email=$email}"}
}val user = User(1, "uncle_bob", "rmartin@objectmentor.com")
println(user) // User{id=1, login=uncle_bob, email=rmartin@objectmentor.com}

解释代码:
通过重写 toString(),我们成功将 User 对象转换为清晰的字符串形式,输出包含所有关键信息。


重写 toString():继承情况

当子类继承父类时,如果父类已经重写了 toString(),子类也会继承这个行为。

比如,我们添加一个 Author 类继承 User,并添加图书信息:

open class User(val id: Int, val login: String, val email: String) {override fun toString(): String {return "User{id=$id, login=$login, email=$email}"}
}class Author(id: Int, login: String, email: String, val books: String): User(id, login, email)val user = User(1, "marys01", "mary0101@gmail.com")
val author = Author(2, "srafael", "rsabatini@gmail.com", "Captain Blood: His Odyssey")println(user)   // User{id=1, login=marys01, email=mary0101@gmail.com}
println(author) // User{id=2, login=srafael, email=rsabatini@gmail.com}

解释代码:
由于 Author 没有重写 toString(),所以调用的是 User 中的重写版本。


为子类单独重写 toString()

现在我们在 Author 中也重写 toString(),并输出书籍信息:

class Author(id: Int, login: String, email: String, val books: String): User(id, login, email) {override fun toString(): String {return "Author{id=$id, login=$login, email=$email}, books: $books"}
}

解释代码:
这样我们就能看到更多信息了:

val user = User(1, "marys01", "mary0101@gmail.com")
val author = Author(2, "ohwilde", "wilde1854@mail.ie", "Someone’s portrait")println(user)   // User{id=1, login=marys01, email=mary0101@gmail.com}
println(author) // Author{id=2, login=ohwilde, email=wilde1854@mail.ie}, books: Someone’s portrait

在子类中调用父类的 toString()

有时候我们希望在子类的 toString() 方法中复用父类的逻辑,这时候可以使用 super

class Author(id: Int, login: String, email: String, val books: String): User(id, login, email) {override fun toString(): String {return "Author: ${super.toString()};\nBooks: $books"}
}

测试一下:

val author1 = Author(1, "uncle_bob","rmartin@objectmentor.com","\n1.\"Clean Code: A Handbook of Agile Software Craftsmanship\" \n2.\"Agile Software Development: Principles, Patterns and Practices\"")val author2 = Author(2, "ltlst","leotolstoy@mail.com","\n1.\"Anna Karenina\" \n2.\"The Death of Ivan Ilyich\" \n3.\"War and Peace\"")println(author1)
println()
println(author2)

输出结果为:

Author: User{id=1, login=uncle_bob, email=rmartin@objectmentor.com};
Books: 
1."Clean Code: A Handbook of Agile Software Craftsmanship" 
2."Agile Software Development: Principles, Patterns and Practices"Author: User{id=2, login=ltlst, email=leotolstoy@mail.com};
Books: 
1."Anna Karenina" 
2."The Death of Ivan Ilyich" 
3."War and Peace"

总结

  • toString() 函数可以将非字符串对象转换为字符串。

  • Kotlin 中的所有类都继承了 Any,因此默认拥有 toString() 方法。

  • 默认情况下,toString() 返回的是类名和内存地址。

  • 你可以通过重写 toString() 自定义对象的打印方式。

  • 对于继承结构,子类可以重用或扩展父类的 toString() 方法。

现在你已经掌握了如何使用和重写 toString() 方法,能够更好地进行调试和信息展示了!

http://www.dtcms.com/a/278275.html

相关文章:

  • S7-1200 中 AT 覆盖参数的应用:灵活访问数据区域的实用指南
  • 借助DeepSeek编写输出漂亮表格的chdb客户端
  • 电流驱动和电压驱动的区别
  • Rust语言实战:LeetCode算法精解
  • iOS高级开发工程师面试——RunLoop
  • FRP Ubuntu 服务端 + MacOS 客户端配置
  • 安装llama-factory报错 error: subprocess-exited-with-error
  • Kubernetes的微服务
  • c语言内存函数以及数据在内存中的存储
  • linux 文件搜索与文件内容查看
  • 嵌入式硬件篇---单稳态多谐施密特电路
  • CISSP通过回顾
  • Java Integer包装类缓存机制详解
  • uni-app 选择国家区号
  • AI与基础设施
  • 微服务引擎 MSE 及云原生 API 网关 2025 年 3 月产品动态
  • 基于光栅传感器+FPGA+ARM的测量控制解决方案
  • Quasar组件库
  • 2025最新android面试指南
  • vue3+arcgisAPI4示例:自定义多个气泡窗口展示(附源码下载)
  • [源力觉醒 创作者计划]_文心大模型4.5开源部署指南:从技术架构到实战落地
  • 知天命的感悟
  • 深入了解linux系统—— 进程信号的保存
  • 1688商品详情接口逆向分析与多语言SDK封装实践
  • Datawhale AI夏令营-基于带货视频评论的用户洞察挑战赛
  • 大数据领域开山鼻祖组件Hadoop核心架构设计
  • 某ctv视频下载逆向思路
  • 【Linux操作系统】简学深悟启示录:Linux权限
  • 算法第三十四天--动态规划part02(第九章)
  • fpga调试经验