这里写自定义目录标题
前言
由于在自己面试过程中,经常被问到有没有学过kotlin,总感觉自己少了点东西,于是就花了一个多星期将最基本的kotlin知识点给学了一遍,本篇文章仅仅含有一点点Android的知识,并不是学习Android的好文章,但是是最快入门kotlin的一篇全面的文章
,当然,我也希望大家与我共同学习进步,如果有什么疑问,或者经验交流,都可以加群QQ:1098392728
与我们交流。
更多好文章可以去浏览我的个人博客WilliamTao的博客
Kotlin学习笔记
1.val和var区别
val 可以理解为java中的final关键字,只能在声明的时候赋值
var 在任何时候都可以赋值
2.简单变量之间的转换
//Float --->Int
val orgin:Float = 65.0f
print(orgin.toInt())
3.数组变量的声明
kotlin中没有Stringarray,而是使用Array ,具体看下面的例子
fun main() {
var int_arrary:IntArray = intArrayOf(1,2,3)
print(int_arrary)
var string_array:Array<String>=arrayListOf("hello","world")
}
其实,上面图片的内容都可以不用,直接使用Array 《》括起来就可以了
数组的获取,可以通过java的中括号,也可以使用get来获取
var string_array:Array<String>=arrayOf("hello","world")
Btn_test.setOnClickListener{
var str :String=""
var i:Int = 0
while(i<string_array.size){
str=str+string_array.get(i)+","
i++
// str=str+string_array[i]+","
}
textView.text=str
println(str)
}
4.字符串
字符串与基本类型的转换
kotlin方便一点,便于记忆
var test:String="1"
println(test.toInt())
字符串常用方法
- indexOf
- substring
- split:在Java里返回的是String[],而在kotlin中返回的是List
- 通过下标获取某个位置的字符
var orgin:String ="he.llo.wor.ld"
var list:List<String> =orgin.split(".")
for(item in list){
print("----"+item+"*----")
}
var orgin:String ="hello,world"
var orgin_trim:String=orgin
if(orgin_trim.indexOf(",")>0){
orgin_trim = orgin_trim.substring(0,orgin_trim.indexOf(","))
}
println("orgin_trim--"+orgin_trim)
println(orgin[1].toString())
println(orgin.get(1).toString())
字符串模板及其拼接
$加变量,如果变量先需要进行计算,则需要加大括号
var name="William_Tao"
print("My name is $name ,and age is ${name.length}")
5.容器
Set
List
Map
公共方法
kotlin允许对容器进行初始化,而java不可以
集合Set/MutableSet
- 循环的方法:
- for
- 迭代器
//方法一
var setList: Set<String> = setOf("test", "second", "thrid")
for (item in setList) {
println("名称: $item")
}
//方法二
var iterator = setList.iterator()
while(iterator.hasNext()){
val item=iterator.next()
println("名称: $item")
}
//方法三
setList.forEach { println("名称: $it") }
缺点所在:
队列List/MutableList
var ListList: List<String> = listOf("test", "second", "thrid")
for (i in ListList.indices) {
var item =ListList[i]
println("名称: $item")
}
list中还提供了两种排序的函数 分别为:
- sortBy
- sortedByDescending
ListList.sortedBy { it.length }
// ListList.sortedByDescending { it.length }
for (i in ListList.indices) {
var item =ListList[i]
println("名称: $item")
}
映射Map/MutableMap
两种初始化的方法:
键值 to 键名
Pair(值 ,名)
var godMap:Map<String,String> = mapOf("苹果" to "Iphone 12","Android" to "VIVO")
var godMap2:MutableMap<String,String> = mutableMapOf(Pair("苹果" , "Iphone 12"), Pair("Android" , "VIVO"))
遍历(同前面那有三种一样,不过有点点区别),见下方
foreach需要 API 24 版本以上才行
//1
for(item in godMap){
println("键名:${item.key}键值:${item.value}")
}
//2
var iterator=godMap.iterator()
while(iterator.hasNext()){
var item = iterator.next()
println("键名:${item.key}键值:${item.value}")
}
//3
godMap.forEach { key, value -> "键名:${key}键值:${value}"}
6.条件分支语句
简单分支
在kotlin中,对分支语句做了优化,
允许分支语句返回字符串
另外,kotlin没有三元运算
//方法一
var flag:Boolean=false
Btn_test.setOnClickListener {
textView.text = if(flag==true){"flag is true"
}else {
"flag is false"
}
flag = !flag
}
//方法二,再一的基础上去掉{}
var flag:Boolean=false
Btn_test.setOnClickListener {
textView.text = if(flag==true)"flag is true"
else
"flag is false"
flag = !flag
}
多路分支
注意与switch case之间的区别
- when 替代了 switch
- 数值 -> 代替了case
- else替代了default
- kotlin中每一个 分支自动跳出
- when -> 同样允许有返回值
- 在java中case后面只能引入常量,但是kotlin允许引入变量判断。
- 在java中case后面只能引入一个常量,如果有多个常量的话,就需要并列写多个,很麻烦,在kotlin中就对此进行了优化,具体见代码
- kotlin中的when ->也支持类型判断(is 变量类型)
//版本一
var count:Int =0;
Btn_test.setOnClickListener {
when(count){
0 -> textView.text="你现在的数值为:0"
1 -> textView.text="你现在的数值为:1"
// else -> textView.text="你现在的数值为:default"
}
count = (count+1)%3
}
//最简化版本
var count:Int =0;
Btn_test.setOnClickListener {
textView.text=
when(count){
0 -> "你现在的数值为:0"
1 -> "你现在的数值为:1"
else -> "你现在的数值为:default"
}
count = (count+1)%3
}
//引入变量可以通过
var count:Int=0
var one:Int =1
var tow:Int =2
Btn_test.setOnClickListener {
when(count){
one -> textView.text="你现在的数值为:0"
tow -> textView.text="你现在的数值为:1"
// else -> textView.text="你现在的数值为:default"
}
count = (count+1)%3
}
koltin对于多个常量并列的优化
var count:Int=0
Btn_test.setOnClickListener {
when(count){
1,3,5,7,9 -> textView.text="你现在的数值为:1,3,5,7,9当中的某个值"
in 10..15 -> textView.text="你现在的数值为:10..15当中的某个值"
else -> textView.text="你现在的数值为:default"
}
count = (count+1)%20
}
kotlin中的when ->也支持类型判断(is 变量类型)
var countType:Number;
var countNumb:Int=0
Btn_test.setOnClickListener {
countNumb = (countNumb+1)%3
countType = when(countNumb){
0->countNumb.toLong()
1->countNumb.toFloat()
else ->countNumb.toDouble()
}
//when ->使用类型的判断
textView.text=when(countType){
//重点关注此段
is Long ->"is long"
is Float ->"is Float"
is Double ->"is Double"
else -> "is error"
}
}
7.循环处理
循环遍历
kotlin废除了for( int i=0;i<n;i++) 这种形式,并且kotlin提供了两种方式
- 变量 in …
- for(i in 容器.indices)
//方法一
var list:Array<String> = arrayOf<String>("朝辞白帝彩云间","千里江陵一日还","两岸猿声啼不住","轻舟已过万重山")
Btn_test.setOnClickListener {
var poem:String=""
for(item in list){
poem = "$poem$item,\n "
}
textView.text = poem
}
//方法二
var list:Array<String> = arrayOf<String>("朝辞白帝彩云间","千里江陵一日还","两岸猿声啼不住","轻舟已过万重山")
Btn_test.setOnClickListener {
var poem:String=""
for(i in list.indices){
if(i%2==0){
poem = "$poem${list[i]},\n "
}else{
poem = "$poem${list[i]}。\n "
}
}
textView.text = poem
}
方法二所带来的问题
解决办法
kotlin引入了一些关键字,具体见下面代码(当然是用Java中的while,do —while都行)
//左闭右开,不包括2 16 ---65
for(i in 16 until 66){
println(i)
}
println("**********")
//每一步走4
for(i in 23..89 step 4){
println(i)
}
println("**********")
//从50开始递减到7
for(i in 50 downTo 7){
println(i)
}
//使用while
var list:Array<String> = arrayOf<String>("朝辞白帝彩云间","千里江陵一日还","两岸猿声啼不住","轻舟已过万重山")
var i:Int=0
while(i<list.size){
println(list[i]+"--")
i++
}
println("-----------")
i=0
do{
println(list[i]+"**")
i++
}while (i<list.size)
跳出多重循环
低配版本
//这里有空语句所以注意时Array<String?> 而非Array<String>
var list:Array<String?> = arrayOf("朝辞白帝彩云间",null,"千里江陵一日还",""," ","两岸猿声啼不住","轻舟已过万重山")
Btn_test.setOnClickListener {
var poem:String=""
var pos:Int=-1
var count:Int=0
while(pos<=list.size){
pos++;
//判断是否为空或者是否是有空串或者空格串
if(list[pos].isNullOrBlank()){
continue
}
if(pos%2==0){
poem = "$poem${list[pos]},\n "
}else{
poem = "$poem${list[pos]}。\n "
}
count++
//若合法行数达到4行,则跳出循环
if(count==4){
break
}
}
textView.text = poem
}
高配版 outside@
//这里有空语句所以注意时Array<String?> 而非Array<String>
var list:Array<String?> = arrayOf("朝辞白帝彩云间",null,"千里江陵一日还",""," ","两岸猿声啼不住","轻舟已过万重山")
Btn_test.setOnClickListener {
var i:Int=0
var is_found =false
//给外循环加一个名叫outside的标记
outside@ while (i<list.size){
var j:Int=0
var item=list[i];
if (item != null) {
while(j<item.length){
if(item[j] == '一'){
is_found=true
break@outside
}
j++;
}
}
i++
}
8.空安全
字符串的有效性判断
声明可空变量
正常默认的变量都是非空的
可以为空的变量,可以在声明前在类型后面加问号
//能调用上面6中方法中的任意一个
var strNotNull:String=""
//只能调用 isNullOrEmpty 和 isNullOrBlank方法,因为其与方法需要求其长度,但可能为空,所以不可以调用后面4种方法
var strCanNull:String?=null
检验空值的运算符
var length_null:Int?
var A:String="123"
Btn_test.setOnClickListener {
//表示为空时返回null,所以返回的变量必须被声明为可空类型
length_null = A?.length
//length_null = A?.length?:-1
//length_null = A!!.length
}
textView.text = length_null.toString()
9.等式判断
结构相等
凡是在Java中实现了equals函数的类,其变量均可在Kotlin中通过运算符“==”和“!=”进行等式判断
这种比较变量结构内部值的行为,kotlin称为结构相等,即模样相等
var helloHe:String="你好"
var helloShe:String="哈喽"
var flag:Boolean=false
var resultCont:Boolean=false
Btn_test.setOnClickListener {
titile.text = "$helloHe 与$helloShe 的对比结果为:"
if(flag){
resultCont=helloHe==helloShe
content.text = "最后的对比结果为:$resultCont"
}else{
resultCont=helloHe!=helloShe
content.text = "最后的对比结果为:$resultCont"
}
flag=!flag
}
引用相等
kotlin中 引用相等用 =,引用不等用!
但是在绝大多数场合,结构相等和引用相等的判断结果是一致的,
var time:Date = Date()
var timeCopy:Any = time.clone();
var count:Int=0
Btn_test.setOnClickListener {
when(count++%4){
0 ->{titile.text="比较time 和timeCopy是否结构相等" ;content.text="==比较的结果为${time==timeCopy}"}
1 ->{titile.text="比较time 和timeCopy是否结构不相等";content.text="!=比较的结果为${time!=timeCopy}"}
2 ->{titile.text="比较time 和timeCopy是否引用相等";content.text="!=比较的结果为${time===timeCopy}"}
3 ->{titile.text="比较time 和timeCopy是否引用不相等";content.text="!=比较的结果为${time!==timeCopy}"}
}
}
前两者提到的等式判断其实比较的是变量,当然,还有一些操作,比如判断一个变量的类型,判断一个数组是否包含某一个数,那么这时就需要用到下面的方法啦
is 和 in
is
!is
具体写法:变量名 is(!is) 类型名称
var A:Double=53.3
print(A is Double)
var B:Double=53.3
print(B !is Double)
在java中如何判断一个数是否在数组中,需要通过循环来实现,而在kotlin中通过in 、!in来实现
var oneArray:IntArray = intArrayOf(1,2,3)
var four:Int=4
var one:Int=1;
print("four is in or not in: ${four in oneArray}")
print("four is in or not in: ${one in oneArray}")
10.函数
与Java声明方式的区别
输入参数的格式
//不带参数的
fun function1(){
tv.text="123";
}
//带参数的
fun function2(str:String){
tv.text="123$str"
}
//可带空的参数的
fun function3(str:String?,num:Int){
tv.text=if(str==null){"123"}else{"123$str"}
}
//调用函数的方法
btn.setOnClickListener{function1();function2("123");function3(null,5)}
输出参数的格式
//不带参数的
fun function1():Unit{
tv.text="123";
}
//带参数的 带返回值的
fun function2(str:String):String{
return "$str";
}
//带输入和输出的
fun function3(str:String?,num:Int):String{
tv.text=if(str==null){"123"}else{"123$str"}
return "success";
}
//调用方法同上一样,没区别
默认参数
fun function2(str:String="指南针"):String{
return "$str";
}
可变参数
vararg 表示其后的参数个数是不确定的
//可变数组为string类型
fun getData(general:String,first:String="first",vararg otherArray:String?):String{
var answer="$general,$first,"
for(item in otherArray){
answer="$answer,$item"
}
return answer
}
//调用实例
btn.setOnClickListener{getData("general","first","second","third");}
//可变数组类型为数组类型(相当于两层的数组)
//可变数组为string类型
fun getData(general:String,first:String="first",vararg otherArray:Array<String>){
var answer="$general,$first,"
for(array in otherArray){
for(item in array){
answer="$answer,$item"
}
}
return answer
}
//调用实例
btn.setOnClickListener{getData("general","first",arrayOf("1","2","3"),arrayOf("4","5","6"));}
几种特殊的函数
1.泛型函数
泛型函数
fun <T> appendString(tag:String,vararg otherInfo:T?):String{
var str:String="$tag"
for(item in otherInfo){
str="$str${item.toString()}"
}
return str
}
var count=0
when(count++%3){
0-> appendString<String>("古代四代发明","造纸术","硬刷术","火药","指南针")
1-> appendString<Int>("古代四代发明",1,2,3);
else -> appendString<Double>("古代四代发明",5.5,5.6,5.7)
}
内联函数(没怎么理解)
简化函数
Kotlin把函数当做一种特殊变量
//常规写法
fun fac(n:Int):Int{
if(n<=1) n
else n*fac(n-1)
}
//简化写法
fun fac(n:Int):Int= if(n<=1) n else n*fac(n-1)
尾递归函数
1函数末尾的返回值重复调用自身函数
2.关键字tailrec
3.使用tailrec编译器会相对应的进行优化(采用循环方式代替递归,从而避免了栈溢出的情况)
tailrec fun findFixPoint(x:Double=1.0):Double=if(x==Math.cos(x))x else findFixPoint(Math.cos(x))
高阶函数
1
var str_array:Array<String> = arrayOf("Hello","world",", ","I'm ");
println("系统默认的最大值比较结果为${str_array.maxOrNull()}")
print("系统默认的最大值比较结果为(高阶函数实现)${maxCoustom(str_array,{a,b->a>b})}")
print("按照长度比较 ${maxCoustom(str_array,{a,b->a.length>b.length})}")
print("按照去除空格之后的长度比较 ${maxCoustom(str_array,{a,b->a.trim().length>b.trim().length})}")
lambda函数
看前面的有个,{a,b->a.length>b.length},这个就是lambda函数
前一部分是输入参数,后面一部分是函数体
//完整写法
fun anonymous(a:String,b:String):Boolean{
var result:Boolean = a.length>b.length
return result
}
11.增强系统函数
扩展函数
扩展高阶函数
.
日期函数
.
单例对象
12.类和对象
类的构造
//类的构造
class easyClass {
init {
println("类的初始化")
}
}
//实例化
var test:easyClass = easyClass()
var test1 = easyClass()
类的构造函数
class easyClass constructor(context:Context,name:String){
init {
println("${name}类的初始化 ")
}
}
为了让类有多个携带不同参数的构造方法,kotlin引入了主构造函数和二级构造函数,具体见下面的代码
跟在类后面的参数是主构造函数的入参;
二级构造函数可以在内部直接书写完整的函数表达式;
class easyClass constructor(context:Context,name:String){
init {
println("${name}类的初始化 ")
}
constructor(context:Context,name:String,sex:Int):this(context,name){
var sexName =if(sex==0) "公" else "母"
println("这是一只名叫${name} 是${sexName}的")
}
}
补充说明:
二级构造函数和普通函数的区别:
上面代码有个问题就是他首先先会执行主构造函数,然后调用二级构造函数,有时候我们并不想让他执行主构造,这时就可以参考如下:把几个构造方法都放在类的内部定义
class easyClass {
constructor(context:Context,name:String){
println("${name}类的初始化 ")
}
constructor(context:Context,name:String,sex:Int):this(context,name){
var sexName =if(sex==0) "公" else "母"
println("这是一只名叫${name} 是${sexName}的")
}
}
带默认参数的构造方法
//类的柱构造方法使用了默认参数
class easyClass constructor(context:Context,name:String,sex: Int=0) {
init {
var sexName =if(sex==0) "公" else "母"
println("这是一只名叫${name} 是${sexName}的")
}
}
实例化
//传入两个参数
var test:easyClass = easyClass(context,"狗")
//传入是三个参数
var test1 = easyClass(context,"狗",20)
为了解决java和kotlin在默认参数定义上的不同,引入了@JvmOverloads,告知编译器这个类是给java重载用的(好比配备了一个同声翻译机,能听得懂Kotlin,也能听得懂Java)
加入@JvmOverloads目的就是让java代码也能识别默认参数
//类的柱构造方法使用了默认参数,引入了 @JvmOverloads
class easyClass @JvmOverloads constructor(context:Context, name:String, sex: Int=0) {
init {
var sexName =if(sex==0) "公" else "母"
println("这是一只名叫${name} 是${sexName}的")
}
}
类的成员
成员变量
//之前写代码为成员变量赋值的方法习惯
class WildAnimal (name:String,Sex:Int=0){
var name:String
val Sex:Int
init {
this.name=name
this.Sex=Sex
}
}
//增加了val(不可变) 和var(可变),通过kotlin某种机制让编译器自动对其成员变量命名的与赋值
class WildAnimal (var name:String,val Sex:Int=0){
}
class WildAnimal (var name:String,val Sex:Int=0){
var SexName:String
init {
SexName=if(Sex==0)"公" else "母"
}
}
成员方法
class WildAnimal (var name:String,val Sex:Int=0){
var SexName:String
init {
SexName=if(Sex==0)"公" else "母"
}
fun getDes(tag:String):String{
return "欢迎来到${tag}:这只${name}是${SexName}"
}
}
//外部调用
WildAnimal("猫",0).getDes("test")
伴生对象
//伴生对象
class WildAnimalCompanion (var name:String,val Sex:Int=0){
var SexName:String
init {
SexName=if(Sex==0)"公" else "母"
}
fun getDes(tag:String):String{
return "欢迎来到${tag}:这只${name}是${SexName}"
}
//companion 表示伴随 object表示对象 WildAnimal表示伴随对象的名称
companion object WildAnimal{
fun judgeSex(sexName:String):Int{
var sex:Int = when(sexName){
"公" ->0
"母" ->1
else->-1
}
return sex
}
}
}
//外部调用----------等价于java中的静态方法调用
print( WildAnimalCompanion.judgeSex("母"))
print(WildAnimalCompanion.WildAnimal.judgeSex("公"))
静态属性
静态属性,静态方法都是在伴生对象中去定义的
class WildAnimalCompanion (var name:String,val Sex:Int=0){
var SexName:String
init {
SexName=if(Sex==0)"公" else "母"
}
fun getDes(tag:String):String{
return "欢迎来到${tag}:这只${name}是${SexName}"
}
//companion 表示伴随 object表示对象 WildAnimal表示伴随对象的名称
companion object WildAnimal{
//静态常量的值是不可以变得,所以需要用val修饰
val MALE=1
val FEMALE=0
val UNKNOW=-1
fun judgeSex(sexName:String):Int{
var sex:Int = when(sexName){
"公" ->MALE
"母" ->FEMALE
else->-UNKNOW
}
return sex
}
}
}
//外部调用静态属性
WildAnimalCompanion.FEMALE
类的继承
开放性修饰符
//父类
open class Bird(name:String,sex:Int){
}
//子类继承Bird
class test(name:String,sex:Int) :Bird(name,sex) {
}
普通类的继承
open class Bird(var name:String,val sex:Int){
var sexName:String
//初始化
init {
sexName=getSexName(sex)
}
//bird内部的一个方法
open protected fun getSexName(sex:Int):String{
return if(sex==MALE)"公" else "母"
}
//伴随对象,包含静态变量和静态方法
companion object BirdStatic{
val MALE=1
val FEMALE=0
val UNKNOW=-1
fun judgeSex(sexName:String):Int{
var sex:Int = when(sexName){
"公" ->MALE
"母" ->FEMALE
else->-UNKNOW
}
return sex
}
}
}
//父类Bird已经在构造函数声明了属性,故Duck无需重复声明属性
//也就是说,子类的构造方法在输入参数时,无需再加val和var
class Duck(name:String="鸭子",sex:Int=Bird.MALE) :Bird(name,sex) {
}
子类重新定义新的成员属性和成员方法
class Ostrich(name:String="鸵鸟",sex:Int=Bird.MALE) :Bird(name,sex) {
override fun getSexName(sex: Int): String {
return if (sex== MALE) "雄" else "雌"
}
}
抽象类
抽象类以及接口中的方法,默认都是open(即是可以被继承的)
abstract class Chicken(name:String, sex:Int, var voice:String) : Bird(name, sex) {
val numberArray:Array<String> = arrayOf("1","2","3")
//抽象方法必须在子类中重写
abstract fun callOut(times:Int):String
}
接口
open class Bird(var name:String,val sex:Int){
var sexName:String
//初始化
init {
sexName=getSexName(sex)
}
//bird内部的一个方法
open protected fun getSexName(sex:Int):String{
return if(sex==MALE)"公" else "母"
}
//伴随对象,包含静态变量和静态方法
companion object BirdStatic{
val MALE=1
val FEMALE=0
val UNKNOW=-1
fun judgeSex(sexName:String):Int{
var sex:Int = when(sexName){
"公" ->MALE
"母" ->FEMALE
else->-UNKNOW
}
return sex
}
}
}
interface Behavior {
//接口内部的方法默认就是抽象类,所以不加abstract也可以,当然open也可以不加
open abstract fun fly():String
//接口内部的所有方法都默认open类型
fun swin():String
//kotlin允许在接口实现方法
fun run():String{
return "和哈哈哈"
}
//kotlin的接口允许声明抽象属性,实现该接口的类必须重载该属性
// open abstract val skillSports:String
val skillSports:String
}
class Goose(name:String="天鹅",sex:Int=Bird.FEMALE) : Bird(name,sex),Behavior {
override fun fly(): String {
TODO("Not yet implemented")
return "fly"
}
override fun swin(): String {
TODO("Not yet implemented")
return "swin"
}
//因为接口已经实现该方法,所以在继承接口的时候此方法可以写也可以不写
override fun run(): String {
return super.run()
}
//重载来自接口的抽象类
override val skillSports: String = "打篮球"
}
//外部调用下·
Goose().fly()
Goose().swin()
Goose().skillSports
接口代理
通过关键字by表示该接口将由入参中的代理类实现、
interface Behavior {
//接口内部的方法默认就是抽象类,所以不加abstract也可以,当然open也可以不加
open abstract fun fly():String
//接口内部的所有方法都默认open类型
fun swin():String
//kotlin允许在接口实现方法
fun run():String{
return "和哈哈哈"
}
//kotlin的接口允许声明抽象属性,实现该接口的类必须重载该属性
// open abstract val skillSports:String
val skillSports:String
}
class BehaviorFly:Behavior {
override fun fly(): String {
return "翱翔天空"
}
override fun swin(): String {
return "落水凤凰不如鸡"
}
override val skillSports: String="飞翔"
}
class BehaviorSwim:Behavior {
override fun fly(): String {
return "看情况,大雁能展翅高飞,企鹅却欲飞还休"
}
override fun swin(): String {
return "怡然戏水"
}
override val skillSports: String="游泳"
}
class WildFowl(name:String,sex:Int=Bird.MALE,behavior: Behavior):Bird(name,sex),Behavior by behavior {
}
//外部调用
WildFowl("老鹰",Bird.MALE,BehaviorSwim())
小结
几种特殊的类
嵌套类
调用嵌套类时,得在嵌套类得类名前添加外部类得类名,相当于把这个嵌套类作为外部类得静态对象使用。
//外部调用嵌套类
//由于嵌套类无法访问外部类得成员,所有七方法只能返回自身的信息
Tree.Flower("桃花")
class Tree(treeName:String) {
// 下面的类访问不到treeName
class Flower(var flowerName:String){
return "$flowerName"
}
}
内部类
class Tree(treeName:String) {
// 下面的内部类可以访问到treeName
inner class Flower(var flowerName:String){
return “$flowerName”
}
}
枚举类
enum class SeasonType {
SPRING,SUMMER,AUTUMN,WINTER
}
enum class SeasonName(val seasonName: String) {
SPRING("春天 "),
SUMMER("夏天"),
AUTUMN("秋天"),
WINTER("冬天")
}
//ordinal 代表枚举类得序号,name代表枚举类得名称
//使用自定义的seasonName代表更个性化的叙述
print(SeasonName.SPRING.ordinal )
println(SeasonName.SPRING.seasonName)
密封类(没太懂)
sealed class SeasonSealed {
//密封类内部的每个嵌套类都必须继承该类
class Spring(var name: String):SeasonSealed()
class Summer(var name: String):SeasonSealed()
class Autumn(var name: String):SeasonSealed()
class Winter(var name: String):SeasonSealed()
}
when(season){
is SeasonSealed.Spring ->season.name
is SeasonSealed.Autumn ->season.name
is SeasonSealed.Summer ->season.name
is SeasonSealed.Winter ->season.name
}
数据类
只需要在class前面加关键字data
data class Plant(var name:String, var stem:String, var leaf:String, var
flower:String, var fruit:String, var seed:String) {
}
外部调用
var lotus =Plant("莲","莲藕","莲花","莲蓬","莲子","莲叶");
var count:Int=0
var lotus2=when(count++%2){
//copy方法带参数,表示指定参数另外赋值,不带参数表示赋值的一模一样
0-> lotus.copy(flower = "荷花")
1->lotus.copy()
else ->lotus.copy(flower = "莲花")
}
var result = if(lotus.equals(lotus2)) "相等" else "不相等"
var text1 = lotus.toString()
var text2 = lotus2.toString()
模板类
在类名后年添加“”,表示这是一个模板类
class River <T>(var name:String,var length:T) {
fun getInfo():String{
var unit:String = when(length){
is String ->"米"
// Int Double.Float,都是Number类型
is Number ->"m"
else ->""
}
return "${name} 的长度是$length $unit"
}
}
var count:Int=0
var lotus2=when(count++%2){
//末班对声明对象时,要在模板类的类名后面加上“参数类型”
0->River<Int>("小溪",100)
//如果编译器根据输入参数就能知晓参数类型也可以省略“参数类型”
1->River("山间",99.5f)
else -> River("大河","一千")
}