最后
这里我希望可以帮助到大家提升进阶。
内容包含:Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。
喜欢本文的话,不妨给我点个小赞、评论区留言或者转发支持一下呗~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
}
}
count++
tv_result.text = “这头 a n i m a l . n a m e 是 {animal.name}是 animal.name是{if (animal.sex == 0) “公” else “母”}的”
}
}
fun setAnimalInfo() {
animalName = “牛”
animalSex = 1
}
}
再看看Java代码中怎么做的
package com.llw.kotlinstart;
public class WildAnimal {
private String name;
private String sex;
public WildAnimal(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
很熟悉吧,因为基本上每一个实体都离不开这一步,
对比一下:
(1)冗余的同名属性声明语句。
(2)冗余的同名属性赋值语句。
(3)冗余的属性获取方法与设置方法。
Kotlin的代码真的精简了很多,鸟枪换炮,
如果某个字段并非入参的同名属性,就需要在类内部显示声明该属性字段,例如,前面WildAnimal类的性别只是一个整型的类型字段,而界面上展示的是性别的中文名称,所以应当给该类补充一个性别名称的属性字段,这样每次访问sexName字段即可获得该动物的性别名称,新建一个名为WildAnimalMember的类,代码如下:
package com.llw.kotlinstart
class WildAnimalMember (val name:String,val sex:Int = 0) {
//非空的成员属性必须在声明时赋值或者在构造函数中赋值,否则编译器会报错
var sexName:String
init {
sexName = if(sex == 0) “公” else “母”
}
}
然后再看一下怎么调用这个类:
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import java.lang.Exception
import java.text.SimpleDateFormat
import java.util.*
class MainActivity : AppCompatActivity() {
var animalName: String = “”
var animalSex: Int = 0
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
setAnimalInfo()
var animal = when (count % 2) {
0 -> {
WildAnimalMember(animalName)
}
else -> {
WildAnimalMember(animalName, animalSex)
}
}
count++
tv_result.text = “这头 a n i m a l . n a m e 是 {animal.name}是 animal.name是{animal.sexName}的”
}
}
fun setAnimalInfo() {
animalName = “牛”
animalSex = 1
}
}
类的成员除了成员属性还有成员方法,在类内部定义成员方法的过程和普通函数定义比较类似。下面增加一个获取动物描述信息的成员方法getDesc(),新创建一个名为WildAnimalFunction的类
package com.llw.kotlinstart
class WildAnimalFunction(var name: String, val sex: Int = 0) {
var sexName: String
init {
sexName = if (sex == 0) “公” else “母”
}
fun getDesc(tag: String): String {
return “欢迎来到 t a g :这头 tag:这头 tag:这头{name}是${sexName}的”
}
}
然后我们在MainActivity.kt中调用这个类的方法
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.WildAnimalFunction
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var animalName: String = “”
var animalSex: Int = 0
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
setAnimalInfo()
var animal = when(count%2){
0 -> WildAnimalFunction(
animalName
)
else -> WildAnimalFunction(
animalName,
animalSex
)
}
tv_result.text = animal.getDesc(“动物园”)
count++
}
}
fun setAnimalInfo() {
animalName = “牛”
animalSex = 1
}
}
伴生对象这个是在Kotlin中有的,Java中没有,什么是伴生对象呢,你可以把它理解为“影子”,把类当做一个人,这个人可以有很多房子,但是人只有一个,影子也只有一个。你也可以把伴生对象替换掉静态成员的作用,但它比静态成员的功能要强大。我们之前通过性别类型来获得性别名称,那么反推呢,我们使用伴生对象来实现这一功能,新创建一个名为WildAnimalCompanion的类
package com.llw.kotlinstart.custom_class
class WildAnimalCompanion (var name: String,val sex:Int = 0) {
var sexName:String
init {
sexName = if(sex == 0) “公” else “母”
}
fun getDesc(tag: String): String {
return “欢迎来到 t a g :这头 tag:这头 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
}
}
}
代码应该没有什么好说的,一目了然,关键定义这个伴生对象和使用它,接下来看怎么使用
代码如下:
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.WildAnimalCompanion
import com.llw.kotlinstart.custom_class.WildAnimalFunction
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val sexArray:Array = arrayOf(“公”,“母”,“雄”,“雌”)
btn_test.setOnClickListener {
var sexName:String = sexArray[count++%4]
//伴生对象的WildAnimal名称可以省略掉
//tv_result.text = "“ s e x N a m e 对 ¨ 应的类型是 sexName\"对应的类型是 sexName对¨应的类型是{WildAnimalCompanion.WildAnimal.judgeSex(sexName)}”
tv_result.text = "“ s e x N a m e 对 ¨ 应的类型是 sexName\"对应的类型是 sexName对¨应的类型是{WildAnimalCompanion.judgeSex(sexName)}”//双引号 要加反斜杠 如同这样 “”
}
}
}
这个是灰色的,我们省略掉也是可以的
有四种结果,我只放两个图
之前我们的伴生对象可以实现静态函数,同样也能实现静态属性,只要在伴生对象内部增加几个字段定义就行了,之前是用0和1表示动物的雄雌,接下来用整型常量MALE表示雄性的0,整型常量FEMALE表示雌性的1,创建一个名为WildAnimalConstant的类,代码如下,
package com.llw.kotlinstart.custom_class
class WildAnimalConstant(var name: String, val sex: Int = MALE) {
var sexName: String
init {
sexName = if (sex == MALE) “公” else “母”
}
fun getDesc(tag: String): String {
return “欢迎来到 t a g : 这只 tag: 这只 tag:这只{name}是${sexName}的。”
}
companion object WildAnimal {
//静态常量的值是不可变得,所以要使用关键字val修饰
val MALE = 0
val FEMALE = 1
val UNKOWN = -1
fun judgeSex(sexName:String):Int{
var sex:Int = when(sexName){
“公”,“雄” -> MALE
“母”,“雌” -> FEMALE
else -> UNKOWN
}
return sex
}
}
}
然后再进行调用
val sexArray:Array = arrayOf(“公”,“母”,“雄”,“雌”)
btn_test.setOnClickListener {
var sexName:String = sexArray[count++%4]
//伴生对象的WildAnimal名称可以省略掉
//tv_result.text = "“ s e x N a m e 对 ¨ 应的类型是 sexName\"对应的类型是 sexName对¨应的类型是{WildAnimalCompanion.WildAnimal.judgeSex(sexName)}”
tv_result.text = "“ s e x N a m e 对 ¨ 应的类型是 sexName\"对应的类型是 sexName对¨应的类型是{WildAnimalConstant.judgeSex(sexName)}”//双引号 要加反斜杠 如同这样 “”
}
改一下类名就可以了,运行效果和之前的是一样的,只不过程序里面就可以通过WildAnimalConstant.MALE和WildAnimalConstant.FEMALE来判断公母了,不像之前通过0和1这种毫无意义的值来判断。
Kotlin的类成员分为实例成员与静态成员,实例成员包括成员属性和成员方法,其中与入参同名的成员属性可以在构造函数中直接声明,外部必须通过类的实例才能访问类的成员属性和成员方法,类的静态成员包括静态属性与静态方法,它们都在类的伴生对象中定义,外部可以通过类名直接访问该类的静态成员。
===================================================================
我们一开始就提到了类的继承,如class MainActivity : AppCompatActivity(),这和Java是不一样的,那么Kotlin怎么定义基类并由基类派生出子类呢?
之前我们写了好多个WildAnimal类,Java和Kotlin关于类的继承还有区别,比如Java中默认每个类都能被继承,除非加了final关键字,而Kotlin刚好相反,它默认每个类都不能被继承(PS:这不是搞我心态吗!!!),这个时候要想让一个类成为基类,就要把该类开放出来,于是就用到了开放性修饰符open(PS:敲黑板,重点来了,哪个),演示代码如下:
open class Animal(var name:String,val sex:Int = 0){
}
在Java中有几个熟悉的关键字,public、protected、private,分别表示公开、只对子类开放、私有。那么在Kotlin中也给出了4个开放性修饰符。
| 开放性修饰符 | 说明 |
| — | — |
| public | 对所有人开放。Kotlin的类、函数、变量不加开放性修饰符的话,默认就是public类型 |
| internal | 只对本模块内部开放,这是Kotlin新增的关键字。 |
| protected | 只对自己和子类开放 |
| private | 只对自己开放、即私有 |
注意到这几个修饰符与open一样都加在类和函数前面,并且都包含“开放”的意思,乍看起来还真有点迷,到底open跟这4个开放性修饰符是什么关系呢?其实很简单,open不控制某个对象的访问权限,只决定该对象能否繁衍开来,说白了,就是公告这个叼毛有没有资格繁衍下一代,只有头戴open帽子的类,才允许作为基类派生出子类来,而头戴open帽子的函数,表示它允许在子类中进行重写,如果没戴open帽子,该类就只好打光棍了,函数没戴open帽子的话,类的孩子就没有办法修改它。
至于那4个开放性修饰符,则是用来限定允许访问某对象的外部范围,通俗地说,就是哪里的帅哥可以跟这个美女搞对象,头戴public的,表示全世界的帅哥都能跟她处对象,头戴internal的,表示只有本国的帅哥可以,头戴protected的,表示自由本单位以及下属单位的可以,头戴private,表示自己本单位可以。
创建一个Poultry类,代码如下:
package com.llw.kotlinstart.custom_class
//Kotlin的类型默认是不能继承的(即 final类型),如果需要继承某类,该父类就应当声明open类型
open class Poultry (var name:String,val sex:Int = MALE){
//变量、方法、类默认都是public,所以一般都把public省略掉了
var sexName:String
init {
sexName = getSexName(sex)
}
//私有的方法既不能被外部访问,也不能被子类继承,因此open与private不能共存,否则编译器会报错
open protected fun getSexName(sex:Int):String{
return if(sex == MALE) “公” else “母”
}
fun getDesc(tag:String):String{
return “欢迎来到 t a g : 这只 tag: 这只 tag:这只{name}是${sexName}的。”
}
companion object BirdStatic{
val MALE = 0
val FEMALE = 1
val UNKOWN = -1
fun judgeSex(sexName:String):Int {
var sex:Int = when (sexName){
“公”,“雄” -> MALE
“母”,“雌” -> FEMALE
else -> UNKOWN
}
return sex
}
}
}
然后我们再创建一个名为Pig的子类,继承Poultry,代码如下:
package com.llw.kotlinstart.custom_class
//注意父类Bird已经在构造函数声明了属性,故而子类Pig无须重复声明属性
//也就是说,子类的构造函数在输入参数前面不需要再加val和var
class Pig(name:String=“猪”,sex: Int= MALE) : Poultry(name, sex){
}
然后在Activity中调用:
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var sex:Int
btn_test.setOnClickListener {
var sexPoultry = if(count++%3==0) Poultry.MALE else Poultry.FEMALE
var pig = Pig(sex = sexPoultry)
tv_result.text = pig.getDesc(“高老庄”)
}
}
}
运行效果图如下:
然后再来定义一个小狗类 Dog的代码
package com.llw.kotlinstart.custom_class
class Dog (name:String = “哈士奇”,sex:Int = MALE):Poultry(name, sex){
override public fun getSexName(sex: Int): String {
return if(sex == MALE) “雄” else “雌”
}
}
然后在Activity中调用
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var sex:Int
btn_test.setOnClickListener {
var sexPoultry = if(count++%3==0) Poultry.MALE else Poultry.FEMALE
var dog = Dog(sex = sexPoultry)
tv_result.text = dog.getDesc(“狗狗流浪记”)
}
}
}
运行效果图如下:
Kotlin中也存在与Java类似的抽象类,抽象类之所以存在,是因为其内部拥有被关键字abstract修饰的抽象方法。抽象方法没有具体的函数体,故而外部无法直接声明抽象类的实例,只有在子类继承时重写方法,方可使用该子类正常声明对象实例。
For Example ,鸡属于鸟类,可是公鸡和母鸡的叫声是不一样的,所以鸡这个类的叫唤方法“callOut”发出什么声音并不确定,只能先声明为抽象方法,连带着鸡类“Chicken”也变成抽象类了。
现在定义一个抽象的Chicken类,代码如下:
package com.llw.kotlinstart.custom_class
//子类的构造函数,原来的输入参数不用加var和val,新增的输入参数必须加var或者val
//因为抽象类不能直接使用,所以构造函数不必默认参数赋值
abstract class Chicken (name:String,sex:Int,var voice:String):Poultry(name, sex){
val numberArray:Array = arrayOf(“一”,“二”,“三”,“四”,“五”,“六”,“七”)
//抽象方法必须在子类进行重写,所以可以省略关键字open,因为abstract方法默认就是open类型
//open abstract fun callOut(times:Int):String
abstract fun callOut(times:Int):String
}
然后我们从Chicken类派生出公鸡类Cock,指定攻击的叫声为“喔喔喔”,同时还要重写callOut方法,明确公鸡的叫唤行为。具体代码如下:
package com.llw.kotlinstart.custom_class
class Cock(name:String=“鸡”,sex:Int = Poultry.MALE,voice:String=“喔喔喔”): Chicken(name, sex, voice) {
override fun callOut(times: Int): String {
var count = when {
//when语句判断大于和小于时,要把完整的判断条件写到每个分支中
times <=0 ->0
times >=7 -> 6
else -> times
}
return “ s e x N a m e sexName sexNamename v o i c e 叫了 {voice}叫了 voice叫了{numberArray[count]}声,这是在报晓”
}
}
再派生出公鸡类Hen,指定攻击的叫声为“咯咯咯”,再重写callOut方法
package com.llw.kotlinstart.custom_class
class Hen(name:String=“鸡”,sex:Int = Poultry.FEMALE,voice:String=“咯咯咯”): Chicken(name, sex, voice) {
override fun callOut(times: Int): String {
var count = when {
//when语句判断大于和小于时,要把完整的判断条件写到每个分支中
times <=0 ->0
times >=7 -> 6
else -> times
}
return “ s e x N a m e sexName sexNamename v o i c e 叫了 {voice}叫了 voice叫了{numberArray[count]}声,这是在下蛋”
}
}
然后在Activity中调用不同的类
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
//调用公鸡类
tv_result.text = Cock().callOut(count++ % 7)
}
}
}
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
//调用母鸡类
tv_result.text = Hen().callOut(count++%7)
}
}
}
运行结果
Kotlin的接口与Java一样是为了间接实现多重继承,由于直接继承多个类可能存在方法冲突等问题,因此Kotlin在编译阶段就不允许某个类同
时继承多个基类,否则会报错,于是,只能通过接口定义几个抽象方法,然后在实现该接口的具体类中重写这几个方法,从而间接实现类似C++多重继承的功能。
在Kotlin中定义接口需要注意以下几点:
(1)接口不能定义构造函数,否则编译器会报错"An interface may not have a constructor"。
(2)接口的内部方法通常要被实现它的类进行重写,所以这些方法默认为抽象类型。
(3)与Java不同的是,Kotlin允许在接口内部实现某个方法,而Java接口的所有内部方法都必须是抽象方法。
Android开发中最常见的接口是控件的点击监听器View.OnClickListener,它内部的点击动作onClick,类似的还有长按监听器、选中监听器等等,它们无一例外都定义了某种行为的事件处理过程。我们可以用一个列子来表达这些,比如鸟儿的飞翔、游泳、奔跑等,下面定义一个行为接口 Behavior。
package com.llw.kotlinstart.custom_class
//Kotlin与Java一样不允许多重继承,即不能同时继承两个及两个以上类
//否则编译器报错"Only one class may appear in a supertype list"
//所以仍然需要接口interface 来间接实现多重继承的功能
//接口不能带构造函数(那样就变成一个类了),否则编译器报错"An interface may not have a constructor"
interface Behavior {
//接口内部的方法默认就是抽象的,所以不加abstract 也可以,当然open也可以不加
open abstract fun fly():String
//比如下面这个swim方法就没有加关键字abstract ,也无须在此实现方法
fun swim():String
//Kotlin的接口与Java的区别在于,Kotlin接口内部允许实现方法
//此时该方法不是抽象方法,就不能加上abstract
//不过该方法依然是open类型,接口内部的所有方法都默认是open类型
fun run():String{
return “大多数鸟儿跑得并不像样,只有鸵鸟、鸸鹋等少数鸟类才擅长奔跑。”
}
//Kotlin的接口允许声明抽象属性,实现该接口的类必须重载该属性
//与接口内部方法一样,抽象属性前面的open和abstract 也可以省略掉
//open abstract var skiledSporte:String
var skiledSporte:String
}
在其他类实现这个接口时,跟类继承一样把接口名称放在冒号后面,也就是说,Java的extends和implement这两个关键字在Kotlin中都被冒号取代了。然后就想重写抽象类的抽象方法一样重写接口的抽象方法,创建一个名为Goose的类,代码如下:
package com.llw.kotlinstart.custom_class
class Goose(name: String = “鹅”, sex: Int = Poultry.MALE) : Poultry(name, sex), Behavior {
override fun fly(): String {
return “鹅能飞一点点,但是飞不高,也飞不远”
}
override fun swim(): String {
return “鹅是会游泳的”
}
//因为接口已经实现了run方法,所以此处可以不用实现该方法,当你也可以实现它
override fun run(): String {
//super用来调用父类的属性或方法,由于Kotlin的接口允许实现方法,因此super所指的对象也可以是interface
return super.run()
}
//重载了来自接口的抽象属性
override var skiledSporte: String = “游泳”
}
然后在Activity中使用
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
tv_result.text = when(count++%3){
0 -> Goose().fly()
1 -> Goose().swim()
else -> Goose().run()
}
}
}
}
运行效果如下图:
调用fly方法
调用swim方法
调用run方法
通过接口固然完成了相应行为,但是鸟类这个家族非常庞大,如果每种鸟都实现Behavior接口,工作量是非常大的,其实鸟类的行为并不多,可以分类为飞禽、水禽、走禽三个行为类
下面是飞禽的行为类代码示例:
package com.llw.kotlinstart.custom_class
class BehaviorFly : Behavior {
override fun fly(): String {
return “翱翔天空”
}
override fun swim(): String {
return “落水凤凰不如鸡”
}
override fun run(): String {
return “能飞干嘛还要走”
}
override var skiledSporte: String = “飞翔”
}
下面是水禽
package com.llw.kotlinstart.custom_class
class BehaviorSwim : Behavior {
override fun fly(): String {
return “看情况,大雁能展翅高飞,企鹅却欲飞还休”
}
override fun swim(): String {
return “怡然戏水”
}
override fun run(): String {
return “赶鸭子上树”
}
override var skiledSporte: String = “游泳”
}
下面是走禽
package com.llw.kotlinstart.custom_class
class BehaviorRun : Behavior {
override fun fly(): String {
return “飞不起来”
}
override fun swim(): String {
return “望洋兴叹”
}
override fun run(): String {
return super.run()
}
override var skiledSporte: String = “奔跑”
}
然后定义一个引用代理类的野禽基类,通过关键字by表示接口将由入参中的代理类实现,野禽基类WildFowl代码如下:
package com.llw.kotlinstart.custom_class
//只有接口才能使用关键字by进行代理操作
class WildFowl (name:String,sex:Int=MALE,behavior: Behavior):Poultry(name,sex),Behavior by behavior{
}
然后在Activity中使用
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
var count: Int = 0
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
var fowl = when (count++ % 6) {
//把代理类作为输入参数来创建实例
0 -> WildFowl(“老鹰”, Poultry.MALE, BehaviorFly())
//由于sex字段是个默认参数,因此可通过命名参数给behavior赋值
1 -> WildFowl(“凤凰”, behavior = BehaviorFly())
2 -> WildFowl(“大雁”, Poultry.FEMALE, BehaviorSwim())
3 -> WildFowl(“企鹅”, behavior = BehaviorSwim())
4 -> WildFowl(“鸵鸟”, Poultry.MALE, BehaviorRun())
else -> WildFowl(“鹂鹃”, behavior = BehaviorRun())
}
var action = when (count % 11) {
in 0…3 -> fowl.fly()
4, 7, 10 -> fowl.swim()
else -> fowl.run()
}
tv_result.text = “${fowl.name}: $action”
}
}
}
运行效果如下:
老鹰的飞翔行为:
凤凰的游泳行为:
大雁的飞翔行为:
企鹅的游泳行为:
鸵鸟的飞翔行为:
鹂鹃的奔跑行为
通过一顿操作之后,总结出Kotlin的类继承与Java相比有所不同,主要体现在以下几点:
(1)Kotlin的类默认不可被继承,若需继承,则要添加open声明,而Java的类默认是允许被继承的,只有添加final声明才表示不能为继承。
(2)Kotlin除了常规的三个开放性修饰符public、protected、private外,另外增加了修饰符internal,表示只对本模块开放。
(3)Java的类继承关键字extends以及接口实现关键字implement在Kotlin中都被冒号所取代。
(4)Kotlin允许在接口内部实现某个方法,而Java接口的内部方法只能是抽象方法。
(5)Kotlin引入了接口代理(类代理)的概念,而Java不存在代理的写法。
==================================================================
一个类可以在单独的代码文件中定义,也可以在另一个类内部定义,后一种情况叫作嵌套类,即A类嵌套在B类之中,听起来和Java的嵌套类是一样的,但其实有所差别,Java的嵌套类允许访问外部类的成员,而Kotlin的嵌套类不允许访问外部类的成员,强行访问则会报错。
下面是示例代码:
package com.llw.kotlinstart.custom_class
class Tree(var treeName: String) {
//在类内部再定义一个类,这个新类称作嵌套类
class Flower(var flowerName: String) {
fun getName(): String {
return “这是一朵$flowerName”
//普通的嵌套类不能访问外部类的成员,如treeName
//否则编译器会报错:" Unresolved reference: *** "
//return “这是 t r e e N a m e 上的一朵 {treeName}上的一朵 treeName上的一朵flowerName”
}
}
}
调用嵌套类时,得在嵌套类的类名前面添加外部类的类名,相当于把这个嵌套类作为外部类的静态对象使用,在Activity中调用代码如下:
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
//使用嵌套类时,只能引用外部类的类名,不能调用外部类的构造函数
val peachBlossom = Tree.Flower(“桃花”)
tv_result.text = peachBlossom.getName()
}
}
}
因为嵌套类无法访问外部类的成员,所以其方法只能返回自身的信息,运行效果图如下:
Kotlin限制了嵌套类不能访问外部类的成员,那还有什么方法可以实现此功能呢?针对该问题,Kotlin另外增加了关键字inner表示内部,把inner加在嵌套类的class前面,然后嵌套类就变成了内部类,所以Kotlin的内部类就相当于Java的嵌套类,而Kotlin的嵌套类则是加了访问限制的内部类。还是在之前的嵌套类Tree中,加一个内部类Fruit ,示例代码如下,
package com.llw.kotlinstart.custom_class
class Tree(var treeName: String) {
//在类内部再定义一个类,这个新类称作嵌套类
class Flower(var flowerName: String) {
fun getName(): String {
return “这是一朵$flowerName”
//普通的嵌套类不能访问外部类的成员,如treeName
//否则编译器会报错:" Unresolved reference: *** "
//return “这是 t r e e N a m e 上的一朵 {treeName}上的一朵 treeName上的一朵flowerName”
}
}
//嵌套类加上inner前缀,就变成内部类
inner class Fruit(var fruitName:String){
fun getName():String{
//只有声明为内部类(添加了关键字inner,才能访问内外部类的成员)
return “这是 t r e e N a m e 长出来的 {treeName}长出来的 treeName长出来的fruitName”
}
}
}
然后在Activity中调用
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
尾声
以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!
下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
droid.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btn_test.setOnClickListener {
//使用嵌套类时,只能引用外部类的类名,不能调用外部类的构造函数
val peachBlossom = Tree.Flower(“桃花”)
tv_result.text = peachBlossom.getName()
}
}
}
因为嵌套类无法访问外部类的成员,所以其方法只能返回自身的信息,运行效果图如下:
Kotlin限制了嵌套类不能访问外部类的成员,那还有什么方法可以实现此功能呢?针对该问题,Kotlin另外增加了关键字inner表示内部,把inner加在嵌套类的class前面,然后嵌套类就变成了内部类,所以Kotlin的内部类就相当于Java的嵌套类,而Kotlin的嵌套类则是加了访问限制的内部类。还是在之前的嵌套类Tree中,加一个内部类Fruit ,示例代码如下,
package com.llw.kotlinstart.custom_class
class Tree(var treeName: String) {
//在类内部再定义一个类,这个新类称作嵌套类
class Flower(var flowerName: String) {
fun getName(): String {
return “这是一朵$flowerName”
//普通的嵌套类不能访问外部类的成员,如treeName
//否则编译器会报错:" Unresolved reference: *** "
//return “这是 t r e e N a m e 上的一朵 {treeName}上的一朵 treeName上的一朵flowerName”
}
}
//嵌套类加上inner前缀,就变成内部类
inner class Fruit(var fruitName:String){
fun getName():String{
//只有声明为内部类(添加了关键字inner,才能访问内外部类的成员)
return “这是 t r e e N a m e 长出来的 {treeName}长出来的 treeName长出来的fruitName”
}
}
}
然后在Activity中调用
package com.llw.kotlinstart
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.llw.kotlinstart.custom_class.*
import kotlinx.android.synthetic.main.activity_main.*
尾声
以薪资待遇为基础,以发展为最终目标,要在高薪资的地方,谋求最好的发展!
下面是有几位Android行业大佬对应上方技术点整理的一些进阶资料。
[外链图片转存中…(img-xngsfcvJ-1714999484416)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!