小白笔记(持续更新中)
1.open: 移除final修饰(继承与重载)
//KT所有的类 默认是final修饰的,不能被继承
open class Test11(val name:String ) {
fun showName(){println("父类 ${name}")}
//KT所有的函数,默认是final修饰的,不能被重写
open fun request(){showName() }
}
class Name (val subName:String):Test11(subName) {
fun showName2(){println("子类 ${subName}")}
override fun request(){showName2()}
}
fun main() {
val person:Test11=Name("王五")
person.request() //调用的是子类方法
}
2.强制类型转换
open class Person(val name:String) {
fun showName(){println("父类 ${name}")}
open fun request(){showName() }
}
class Student (val subName:String):Person(subName) {
fun showName2(){println("子类 ${subName}")}
override fun request(){showName2()}
}
fun main() {
//父类引用子类对象
val p:Person= Student("王五")
//判断p是否为Person类型 返回true/false
println(p is Person)
//由于p为Person类型,不能调用Student的独有方法
//p.showName2() 报错
//将p强制转换为Student类型
(p as Student).showName2() //将Person类型转换为Student类型,可以调用Student的独有方法
}
3.智能类型转换
open class Person1(val name:String) {
fun showName(){println("父类 ${name}")}
open fun request(){showName() }
}
class Student1 (val subName:String):Person1(subName) {
fun showName2(){println("子类 ${subName}")}
override fun request(){showName2()}
}
fun main() {
val person:Person1=Student1("王五")
//if内部 做了智能类型转换,person为Student1类型,可以调用它的独有方法
if (person is Student1){
//Smart cast to fivecontent.Student1 智能转换类型根据 is 后的类型转换
person.showName2()
//没有提示做了智能转换
person.showName()
}
//val person: Person1 类型不为Student1 无法调用它的独有方法
//person.showName2()
//一般is + as 一起使用进行类型转换
if (person is Person1){
//此时person的智能转换类型为Person1 无法调用Student1的独有方法
//person.showName2() //报错
//用as将Person1转换为Student1类型,可以调用Student1的独有方法
(person as Student1).showName2()
}
}
4.Any超类
//KT中,所有的类都隐式继承了 :Any() 默认就有,可以不写
//Any类在KT设计中: 只提供标准,你看不到实现,实现在各个平台处理好了 例如:Window等等
class Test04 :Any() {
}
// Any==java Object
fun main() {
println(Test04().toString())
}
5.object 类名 {} 对象声明(单例)
//private Test05() {} 主构造方法私有化,所以不加()
object Test05 {
//static {
// Test05 var0 = new Test05();
// INSTANCE = var0;
// String var1 = "init....";
// System.out.println(var1);
// }
//主构造方法私有化,init内容在static静态代码块中执行
//静态代码块中还执行单例INSTANCE的初始化
init {
println("init....")
}
fun show()= println("我是show函数")
}
fun main() {
//Test05 背后代码:Test05.INSTANCE
//既是单例的实例,又是类名,只有一个创建,这就是典型的单例
println(Test05) //fivecontent.Test05@7f63425a
println(Test05) //fivecontent.Test05@7f63425a
println(Test05) //fivecontent.Test05@7f63425a
println(Test05) //fivecontent.Test05@7f63425a
//Test05.show() 背后代码:Test05.INSTANCE.show()
println(Test05.show())
}
6.对象表达式 object:父类()/接口 {}(new子类/实现类对象的一种方式)
//Kt接口
interface RunnableKt{
fun run(){}
}
open class Test06 {
open fun add(){}
open fun del(){}
}
fun main() {
//匿名对象表达式方式 类似于Java中的匿名内部类
//object:Test06() 继承了Test06
//父类引用子类对象
val test:Test06=object:Test06(){
override fun add() {
println("我是add")
}
override fun del() {
println("我是del")
}
}
test.add()
test.del()
//具名实现方式
//父类引用子类对象
val test1:Test06=Test06Impl("王五")
test1.add()
test1.del()
//对Java的接口 使用对象表达式方式
val runnable=object :Runnable{
override fun run() {
println("执行run方法......")
}
}
runnable.run()
//对Java接口 使用java lambda
val runnable1=Runnable { println("执行run方法......") }
runnable1.run()
//对Kotlin接口 使用对象表达式
object :RunnableKt{
override fun run() {
println("执行kotlin run方法......")
}
}.run()
//对kotlin接口 使用Java lambda 不可以使用 会报错
//RunnableKt{ println("执行kotlin run 方法")}
}
class Test06Impl(val name:String):Test06(){
override fun add() {
println("我是add")
}
override fun del() {
println("我是del")
}
}
7.伴生对象 companion object{}(类似于Java中的static)
//在KT中没有Java里的static静态 伴生对象很大程度上与Java的static静态相同的
class Test07 {
//public static final Test07.Companion Companion
//静态不可变对象(静态单例)
companion object{
//private static (final) String info = "信息";
//私有静态属性
val info="信息"
// var info="信息"
fun show(){"开始展示"}
}
}
fun main() {
println(Test07.info)
println(Test07.show())
}
8.inner class 内部类 与 嵌套类(在class中的class)
//内部类可以访问外部类(属性 方法)
class Test08 {
//背后的代码: public static final class NeiBuLei
//inner 移除了static 使得NeiBuLei由外部类变为了内部类
//外部类要想成为内部类 需要用inner修饰去掉static
val name="内部类"
fun show(){NeiBuLei().run()}
fun showage(){NeiBuLei().age}
//内部类
inner class NeiBuLei{
//内部类中不能有静态字段和静态方法
// companion object{}
val age=5
fun run()= println(name)
fun showNei()=show()
}
}
//嵌套类不能直接调用外部类的非静态成员属性
class Wai(){
val name2="嵌套类的外部类"
fun showQian()=QianTao().name1
companion object{
val name3="嵌套类的外部类"
}
class QianTao(){
val name1="嵌套类"
fun show()=Wai().showQian()
// fun showName1()= println(name2) 报错
fun showName()= println(name3)
}
}
fun main() {
//内部类的调用方式,因为内部类不是静态类
Test08().NeiBuLei().showNei()
//嵌套类的调用方式 因为嵌套类是静态类
Wai.QianTao().showName()
}
9.data class 类名(){} 数据类
//普通类 包含属性 get/set函数 构造函数
class JavaBean(var name:String,val age:Int,val data:String ) {}
//数据类 包含属性 get/set函数 构造函数 解构操作 copy toString hashCode equals
data class JavaBean1(var name:String,val age:Int,val data:String ) {}
fun main() {
val bean1 = JavaBean("f", 78, "ff")
println(bean1)
val bean2 = JavaBean("f", 77, "ff")
println(bean2)
//比较的是值
println(bean1==bean2)
//比较的是引用是否相同
println(bean1===bean2)
val bean3 = JavaBean1("f", 78, "ff")
//数据类有自己的toString()方法
println(bean3)
val bean4 = JavaBean1("f", 77, "ff")
println(bean4)
//比较的是参数的值是否相同 不相同返回false
println(bean3==bean4)
//比较的是引用是否相同
println(bean3===bean4)
}
10.copy函数
data class Test10(val name:String,val data:String) {
var age=0
constructor(name:String):this(name,"xiao"){
age=55
}
//重写toString方法
override fun toString(): String {
return "name:$name age:$age"
}
}
fun main() {
val p=Test10("小刘","小刘")
println(p)
//copy函数返回一个调用主构造函数创建的本类实例对象(与次构造方法无关)
val person=p.copy("小六","小刘")
println(person)
//这里的比较还是做为数据类的比较 比较方式:比较参数的值是否相同
//值不相同的返回false
println(person==p)
//次构造函数中初始化了age的值 所以为55
val test10 = Test10("小刘")
println(test10)
//copy没有用到次构造函数,所以age为0
val test=test10.copy("小七","小八")
println(test)
}
11.解构声明 从component1开始
class Test11 (val name:String,val age:Int,val sex:Char) {
//operator 运算符重载
//解构声明 必须从component1开始按顺序声明,不能从component0开始声明
operator fun component1()=name
operator fun component2()=age
operator fun component3()=sex
}
//数据类
data class CopyClass (val name:String,val age:Int,val sex:Char) {}
fun main() {
val(name,age,sex)=Test11("小刘",55,'女')
val(name1,age1,sex1)=CopyClass("小刘",55,'女')
println("name:$name age:$age sex:$sex")
println("name:$name1 age:$age1 sex:$sex1")
//_拒接收对应数据
val(_,age2,_)=CopyClass("小巴",78,'男')
println("age:$age2")
}
12.运算符重载 operator
class Test12 (val number1:Int,val number2:Int) {
//加法
operator fun plus(p1:Test12):Int{
return (number1+number2)+(p1.number1+p1.number2)
}
}
fun main() {
//Java代码:int var0 = (new Test12(5, 10)).plus(new Test12(10, 20));
println(Test12(5,10)+Test12(10,20))
}
13.枚举类 enum class 类名{}
//KT想表达: 枚举其实也是一个class
enum class Week {
星期一,
星期二,
星期三,
星期四,
星期五,
星期六,
星期日;
}
fun main() {
println(Week.星期五)
println(Week.星期三)
//枚举的值 等价于 枚举类本身
println(Week.星期六 is Week) //true
}
14.枚举类中定义函数
class People(var name:String,var number:Int){}
enum class PeopleEnum(private var people:People) {
//枚举值括号里的参数要与主构造函数的入参保持一致
RIGHT_HAND(People("右手",80)),
LEFT_HAND(People("左手",80)),
RIGHT_FOOT(People("右脚",160)),
//枚举要以 ; 结尾
LEFT_FOOT(People("左脚",160));
fun show(){
println("部位:${people.name},长度:${people.number}")
}
fun updateInfo(people2: People){
this.people.number=people2.number
this.people.name=people2.name
println("更新后: 部位:${people.name},长度:${people.number}")
}
}
fun main() {
//枚举类调用方法
PeopleEnum.LEFT_HAND.show()
//枚举更新信息的方法
PeopleEnum.LEFT_HAND.updateInfo(People("左腿",56))
}
15.代数数据类型
enum class Stu{
Level1,
Level2,
Level3,
Level4,
Level5;
}
class Test15(private val stu: Stu) {
fun show():String {
return when (stu) {
Stu.Level1 -> "等级1"
Stu.Level2 -> "等级2"
Stu.Level3 -> "等级3"
Stu.Level4 -> "等级4"
Stu.Level5 -> "等级5"
//else-> 由于我们的show函数,是使用枚举类类型来做判断处理的,这个就属于 代数数据类型 就不需要写else了
}
}
}
fun main() {
println(Test15(Stu.Level4).show())
}
16.密封类 sealed class 类名{}
密封类本身是 abstract 的:它不能直接实例化,可以有抽象(abstract) 成员。
不允许有 非 private修饰的构造函数(其构造函数默认是 private)
扩展密封类的类(子类)必须与密封类在同一文件中
扩展密封类子类的类(间接继承者)可以放在任何位置,而无需在同一个文件中
//密封类的构造函数默认是private
//Java: public abstract class Level abstract修饰类,Level不能被实例化
sealed class Level {
//都要继承密封类
//object Level1 Level2都不需要任何成员 所以一般写成object
object Level1:Level()
object Level2:Level()
//Level3 有成员属性 可以创建不同的实例对象 所以用object不合理 用class合理
class Level3(val levelName:String):Level()
}
class Test16(private val level: Level){
fun show():String{
return when(level){
is Level.Level1->"等级一"
is Level.Level2->"等级二"
//is判断是否这个类型 this.level会智能转换类型为对应的类型 不需要再用as做类型转换
is Level.Level3->"这个等级级别为: ${(this.level as Level.Level3).levelName}"
}
}
}
fun main() {
println(Test16(Level.Level1).show())
println(Test16(Level.Level2).show())
println(Test16(Level.Level3("等级三")).show())
}
17.数据类使用条件
条件一: 服务器请求回来的响应的JavaBean LoginResponseBean 基本上可以使用 数据类
条件二: 数据类至少必须有一个参数的主构造函数
条件三: 数据类必须有参数 var val 的参数
条件四: 数据类不能使用 abstract open sealed inner 等等修饰
条件五: 有这些需求的: 比较 copy toString 解构 等等 可以使用数据类
data class Test17(val name:String) {}