类的超类是 Any 类,Any 类有 equals()、 hashCode() 与 toString()这三个方法,相当于 Java 的 Object 类。
定义类
- 格式
class 类名 [可见性修饰符][注解] [constructor] (Params){ }
定义一个类,赋予属性值,自动生成 get 和 set 方法,若有特殊处理,则可以重写 get 和 set 方法。
主构造函数没有任何注解或者可见性修饰符,可以省略 constructor 关键字。
- val 定义的属性值只有 get 方法
- var 定义的属性值有 set 和 get 方法
class Teacher {
//性别 var定义的属性值有get和set方法
var sex: Int = 1
//国家 val定义的属性值只有get方法
val nation: String = "中国"
}
可见型修饰符
- private
意味着只在这个类内部(包含其所有成员)可见; - protected
在子类中可见 - internal
能见到类声明的 本模块内 的任何客户端都可见其 internal 成员; - public
能见到类声明的任何客户端都可见其 public 成员。
field 关键字
只在 get 和 set 方法中使用。
class Teacher {
//姓名
var name: String? = null
get() = field?.uppercase()
set(value) {
field = value?.trim()
}
//年纪
var age: Int = 18
get() {
return field + 1
}
set(value) {
field = value + 1
}
}
计算属性
类内部自动生成的属性
class Teacher {
//幸运号码 计算属性
val luckyNo
get() = (1..100).random()
}
属性解构
component 函数
//类属性解构
class Book(var type: Int, val name: String) {
operator fun component1() = type
operator fun component2() = name
}
fun testBook() {
val (type, name) = Book(1, "数学")
print("$type is $name")
}
类比较
==在类比较的时候也是比较引用,因为类的超类的是 Any 类
class Student(
_name: String,
var age: Int,
var sex: Int = 1
) {
var name = _name
get() = field.lowercase()
constructor(name: String) : this(name, 18, 1) {
this.name = name.trim()
}
}
fun test() {
//==,比较引用,类继承Any类,所以这里也是引用
//===,比较引用
print(Student("小明") == Student("小明"))//false
print(Student("小明") === Student("小明"))//false
}
类初始化
主构造函数
- 临时变量使用下划线加变量名
- 更推荐使用定义变量的方式作为参数
class Student(
_name: String,//临时变量使用下划线
var age: Int,//直接定义变量的方式作为参数,更推荐这种方案
var sex: Int = 1//默认参数,使用时不传入这个值则使用默认1
) {
//只赋值一次
var name = _name
get() = field.lowercase()
}
fun test() {
val student = Student("Elaine", 18, 1)
print("name:" + student.name)
print("age:" + student.age)
}
次构造函数
使用 constructor 关键字,在主构造函数之上传入默认值,然后可以将传入的值进行初始化操作。次构造函数必须直接或者间接地委托到主构造函数,使用关键字 this。
class Student(
_name: String,
var age: Int,
var sex: Int
) {
var name = _name
get() = field.lowercase()
//次构造函数
constructor(name: String) : this(name, 18, 1) {
this.name = name.trim()//定义初始化代码
}
//次构造函数
constructor(name: String, age: Int) : this(name, age, 1)
}
fun test() {
val student = Student("Elaine")
print("name:" + student.name)
print("age:" + student.age)
}
初始化代码块 init
对传入的参数进行特殊处理,比如空判断等
class Student(
_name: String,
var age: Int,
var sex: Int = 1
) {
var name = _name
get() = field.lowercase()
//初始化代码块
init {
//验证名字是否为空
require(_name.isNotEmpty()) { print("name is empty") }
}
}
fun test() {
val student = Student("")
}
初始化顺序
- 主构造函数里声明的属性
- 类级别的属性赋值或者 init 初始化块里的属性赋值和函数调用(看谁写在前面谁先执行)
- 次构造函数里的属性赋值和函数调用
顺序
延迟初始化和惰性初始化
- 延迟初始化:
使用 lateinit 关键字,需要主动进行初始化或者判断属性是否初始化了
class Student(
_name: String,
var age: Int,
var sex: Int = 1
) {
var name = _name
get() = field.lowercase()
constructor(name: String) : this(name, 18, 1) {
this.name = name.trim()
}
//延迟初始化变量,需要主动初始化
lateinit var myClass: String
//报名课程
fun getClass() {
myClass = "math"
}
//开始学习
fun startLearn() {
//判断课程是否初始化了,是则开始学习
if (::myClass.isInitialized) print("开始学习《$myClass》")
}
}
fun test() {
val student = Student("Elaine")
student.getClass()
student.startLearn()
}
- 惰性初始化:
当调用惰性初始化的值的时候,才会去初始化,类似单例模式里的懒汉模式
class Student(
_name: String,
var age: Int,
var sex: Int = 1
) {
var name = _name
get() = field.lowercase()
constructor(name: String) : this(name, 18, 1) {
this.name = name.trim()
}
//惰性初始化,当调用这个属性值的时候才去初始化
val run by lazy {
getReadyForRun()
}
private fun getReadyForRun(): String {
print("我已经穿好运动鞋了")
return "我可以跑了"
}
}
fun test() {
val student = Student("Elaine")
student.run//调用了才初始化
}
继承和方法重写
使用关键字 open 开放父类以及类的方法
- is 关键字进行类型判断
- as 关键字进行类型转换
open class People(_type: String) {
var type = _type
open fun eat() {
Log.e("people", "吃米饭")
}
}
//子类继承父类
class Older : People("老人") {
//重新方法
override fun eat() {
Log.e("people", "吃偏软的米饭")
}
fun walk() {
Log.e("people", "散步")
}
}
fun testPeople() {
val people: People = Older()
people.eat()//打印结果:people: 吃偏软的米饭
//类型判断
print(people is People)//true
print(people is Older)//true
//类型转换
if (people is Older) {
(people as Older).walk()
}
}
object 关键字
定义只能产生一个实例的类。
- 对象声明
//一个类,是单例
object SingleManager {
//类方法
fun getSingleName(): String {
return "单例名字"
}
}
fun testSingleManager() {
print(SingleManager.getSingleName())
}
- 表达式
//对象
open class Phone {
open fun call() = "可以打电话"
}
fun testPhone() {
//表达式
val androidPhone = object : Phone() {
override fun call(): String = "安卓手机可以打电话"
}
print(androidPhone.call())
}
- 伴生对象
一个类只能有一个伴生对象,使用关键字 companion object
//伴生对象
open class LuckNum {
companion object {
private const val luckyNo = "10008"
fun load() = "测试 $luckyNo"
}
}
fun testLuckNum() {
LuckNum.load()
}