# Kotlin 学习记录一进阶
类与对象
主要是说明 Kotlin 中的面向对象概念。
函数
1. 函数的结构
//函数的声明
fun putPrint(s: String): String{
printIn(s)
return s
}
//函数的调用
putPrint("Hello World")
2. 函数的返回值
//在函数方法后面加上 : 返回类型
fun add(x: Int,y: Int): Int{
return x + y
}
//没有返回类型的话
fun test(){
}
fun test(): Unit{
}//Unit类似于Java中的void
3. 函数的参数
//声明一个加法函数
fun add(x: Int,y: Int): Int{
return x + y
}
//调用
add(1,2)
//命名参数
add(x=1,y=2)
//位置参数命名参数混用
fun test(a: String,b: String,c: String,d: String){
}
//调用:命名参数必须在位置参数之后
test("1","2",c="3",d="4")
//无法确定参数,变参,底层通过数组传递,可接受多个参数,也可以接受零个参数
fun sum(vararg n: Int): Int{
var rel = 0
for(a in n){
rel += a
}
return rel
}
//调用
sum()
sum(1)
sum(1,2)
sum(1,2,3)
//传入数组到变参中,使用*号
val intArray = intArrayOf(1,2,3)
sum(*intArray)
//参数中的默认值
fun test(name: String,age: Int = 19){
}
//调用
test("xiaoming")
4. 函数返回值
//定义一个取绝对值函数
fun abs(x: Int): Int{
if(x > 0){
return x
} else {
return -x
}
}
//可以简化为
fun abs(x: Int) = if(x > 0) x else -x
类
//语法
[访问控制符] class 类名{
属性
方法
}
//在Kotlin中当一个类没有实体时,可以省略{}
class A(val a: String)
//定义一个电脑类
class Computer{
//cpu数量
var cpu = 2
//容量
var disk = 1024
//方法
fun running(){
printIn("运行中")
}
fun turnOn(){
printIn("启动中")
}
fun shutDown(){
printIn("关闭中")
}
}
构造方法
1. 主构造方法
Kotlin 中主构造方法有且只有一个,所有的对象创建时必须使用主构造方法进行初始化,主构造方法紧随类的声明之后
//语法
class 类名 访问控制符 constructor (属性){
}
//例子
class Button (var test: String = "click",val with: Int,val height: Int){
}
//初始化代码块儿
class Button constructor(var test: String,val with: Int,val height: Int){
//初始化代码块儿,跟随类对象实例化被调用
init{
}
}
2. 副构造方法
作用是辅助主构造方法来创建对象,一个类只能有一个主构造方法,但是可以拥有零个或者无数个副构造方法
class Button constructor(var test: String,val with: Int,val height: Int){
//副构造方法一,调用主构造方法
constructor(text: String): this(text,0,0)
//副构造方法二,调用主构造方法
constructor(with: Int, hright: Int): this("",with,height)
//副构造方法三,调用副构造方法一
constructor():this("默认按钮")
}
//创建对象
//调用主构造方法
var button1 = Button("click",100,100)
//调用副构造方法一
var button2 = Button("click")
//调用副构造方法二
var button3 = Button(100,100)
//调用副构造方法三
var button4= Button()
属性
Kotlin 中只能定义属性,属性既可以定义在类中,也可以定义在构造方法中,属性在定义之后几必须进行初始化。
1. 默认的Getter和Setter
//创建电脑类
//val 只读类型
class Computer(val disk: String) {
//可读可写类型
var cpu: Int = 0
}
fun main(){
val computer = Computer("200GB")
//默认调用Setter
computer.cpu = 2
//默认调用Getter
val disk = computer.disk
}
2. 延迟初始化属性
使用延迟初始化
- 必须定义在类中
- 必须使用默认访问器
- 必须声明var
- 必须是非空类型
- 必须是非基本数据类型
class MainActivity {
//声明延迟初始化属性
lateinit var button: Button
fun onCreate(){
//初始化属性
button = Button()
button.text = "OK"
}
}
3. 内联属性
内联属性要求:数据值有访问器没有幕后字段
class Student{
var loginName = ""
inline var username: String
get() = loginName
set(value){
this.loginName = value
}
}
方法
方法就是定义在类中的函数,使用方法和使用函数类似。
1. infix方法
被infix修饰的方法,在调用时可以省略点符号和括号,注意这种方法只能有一个参数。
class Student{
var height = 0
//infix修饰的方法
infix fun height(height: Int) {
this.height = height
}
}
fun main(){
//创建对象
val student = Student()
//方式一普通调用
student.height(180)
//方式二 infix特性调用,省略点符号和括号,但是需要加空格
student height 180
}
2. componentN方法
这种方法主要用于获取对象属性值
class Student(val name: String){
var height: Int = 0
operator fun component1(): String{
return name
}
operator fun component2(): Int{
return height
}
}
//调用
val student = Student("xiaoming")
student.height = 180
val name = student.component1()
val height = student.component2()
类进阶
1. 嵌套类
嵌套类是一种定义在类内部的类,嵌套类与外部类都是独立的存在,无法访问外部类的成员。
//外部类
class Outer{
val outProperty: String = "外部类属性"
//嵌套类
class Nested{
val nestedProperty: String = "内部类属性"
fun doSomthing(){
printIn(outProperty)//无法访问
}
}
}
//创建对象
//通过 外部类.嵌套类 创建嵌套类
val nested = Outer.Nested()
//调用嵌套类方法
nested.doSomthing()
2. 内部类
内部类使用关键字 inner 修饰,定义在类内部的类,作为外部类的成员存在了,可以访问外部类的成员。
//外部类
class Outer{
val name: String = "外部类属性"
//内部类
inner class Nested{
val nestedProperty: String = "内部类属性"
fun getOutName() = name
}
}
//创建对象,外部类创建的时候同时会创建内部类对象
val out = Outer()
//通过外部类对象创建内部类对象
val nested = out.Inner()
//访问外部类属性
nested.getOutName()
单例对象
单例对象被 object 修饰,这种类只有一个实例,并且在创建过程中是线程安全的。
//单例对象
object Singleton{
private var num = 0
fun sum(): Int{
num += 1
return num
}
}
//调用
printIn(Singleton.sum())//打印1
printIn(Singleton.sum())//打印2
printIn(Singleton.sum())//打印3
伴生对象
伴生对象是一种 companion 关键字修饰的、定义在类中的单例对象。伴生对象在声明时可以省略类名。一个类只能有一个伴生对象。
class Dialog(val title: String,val message: String){
companion object Factory{
fun do()
}
}
//调用
Dialog.Factory.do()
Dialog.do()
对象表达式——匿名类
//创建接口
interface Valuable{
fun getPrice(): Int
}
//创建抽象类
abstract class Item{
abstract var group: String
}
fun main(){
var bluBottle = object : Item(),Valuable{
override fun getPrice(): Int {
return 100
}
override var group = "药物"
}
System.out.println(bluBottle.group)
}
//直接创建匿名对象
val redBottle = object {
fun getPrice(): Int{
return 100
}
var group = "药物"
}
//匿名对象类型限制
//将匿名对象保存到本地变量或者私有属性,或者将匿名对象作为私有方法的返回值
//那么程序可以获得匿名对象的真实类型,并且访问到宁明对象中的成员
//将匿名对象定义为共有方法的返回值或者公有属性
//那么程序中只能获得匿名对象 的父类,无法访问对象表达式中的成员
open class Parent{
val y: String = "y"
}
class Child{
//私有方法
private fun privateM() = object: Parent{
val x: String = "x"
}
//公有方法
fun publicM() = object: Parent{
val x: String = "x"
}
fun text(){
//调用私有方法创建的对象,返回真实类型
val privateM = privateM()
//访问对象表达式中的属性
privateM.x
//访问父类型中的属性
privateM.y
//调用公有方法创建对象,返回父类型的Parent
val publicM = publicM()
//只能访问父类型中的属性
publicM.y
}
}
继承
在 Java 中所有的类默认都可以被继承,而 Kotlin 相反,所有类默认都隐式被 final 修饰,无法被继承,想要实现继承功能需要:
- 在父类声明语句的最前面加上 open 关键字;
- 在子类声明语句之后加上 : 和父类类型
open class Parent{}
class Son: Parent(){}
//子类调用父类构造
open class View(val width: Int,val height: Int)
//子类一,调用父类主构造方法
class SmallView(width: Int,height: Int): View(width,height)
//子类二,调用父类副构造方法
class DefaultView : View()
//子类三,副构造方法调用了父类的主构造方法
class ListView: View{
constructor(width: Int,height: Int): super(width,height)
}
//子类重写父类方法
open class View(val width: Int,val height: Int){
//使用open声明该方法可以被重写
open fun onDraw(){
}
}
class SmallView(width: Int,height: Int) : View(width,height){
override fun onDraw(){
//调用父类的onDraw方法
super.onDraw()
}
}
//子类重写父类属性
open class View(val width: Int,val height: Int){
//使用open声明该属性可以被覆写
open var size: Int = 0
}
//方式一通过赋值语句重写
class SmallView(width: Int,height: Int) : View(width,height){
override var size: Int = width * height
}
//方式二通过Getter访问器重写
class SmallView(width: Int,height: Int) : View(width,height){
override var size: Int = width * height
get() = width * height
}
//子类访问父类的成员
open class View(val width: Int,val height: Int){
//使用open声明该属性可以被覆写
open var size: Int = 0
}
class SmallView(width: Int,height: Int) : View(width,height){
override var size: Int = width * height
inner class Painter{
//内部类访问外部类成员
fun getOutSizeClass(): Int = size
//内部类访问外部类父类成员
fun getOutSuperClass(): Int = super@SmallView.size
}
}