Kotlin笔记 第八章 (一)扩展方法与扩展属性.md

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Leslie_LN/article/details/82895852

1、扩展方法

直白一点就是动态为类增加方法(而java是不支持的,java是静态语言,当一个类定义完成后,程序无法为该类增加、删除属性、方法,除非重写编辑该类的源代码(.java文件),重新编译),*当为父类添加了扩展方法,其子类也将继承到该方法;可以为任何类无论是形同定义的类还是自定义的类添加扩展方法
*

1.1、语法格式

fun		类名(或者接口).方法名(){



	}

如:定义了两个具有继承关系的类

	open class SuperCalss{
		var loc:Int=1; 
		
		fun test(){
			
			}

		} 



	class SubClass:SuperClass(){
		

		fun sub(){

		}


	}

扩展父类SuperClass方法

fun SuperClass.info(){

	println("这是扩展方法"+this.loc)
	}

我们可以通过子类对象来调用从父类继承到扩展方法:

	var sub=SubClass();
	sub.info()

	var sub:SuperClass=SubClass()
  1. 在扩张方法中也可以像成员方法中一样使用this关键字,this代表调用该方法的对象
  2. 扩展方法中既可以调用被扩展类的成员方法、属性也可以调用定义所在类的成员

1.2、扩展实现机制

当为类添加了扩展方法,被扩展的类并没有被修改,还是原来的类。
扩展方法本质:定义一个函数,当调用扩展方法是,在编译时期执行静态解析(根据调用对象、方法名找到扩展方法,转为函数调用)比如:list.shuffle()

步骤:

  1. 检查list类型,发现是List类型
  2. 检查其类本身是否定义了shuffle方法(成员方法),如果该类包含该方法,直接编译即可
  3. 如果该类不包含该成员方法,就转而查找是否包含该扩展方法,有,则Kotlin编译期执行静态解析,没有编译期报错

成员方法是动态解析(由运行时类型决定),扩展方法是静态解析(由编译时类型决定)不存在多态

例如:以上面代码为例,在***为子类SubClass为添加一个和父类相同签名的扩展方法(不需要声明为方法重写)***:

fun SubClass.info(){
		println("子类扩展方法")

	}


	var sub:SuperClass=SubClass();
	sub.info();

将调用的是父类的info()方法;

当类存在相同签名的成员方法和扩展方法时,成员方法优先级高于扩展方法,即系统总是调用成员方法而不是扩展方法

当成员方法和扩展方法只是相同方法名,形参列表不同,不会出现成员方法遮挡扩展方法的情况,系统是可以区分调用成员方法还是扩展方法

1.3、扩张方法定义位置

  1. 以顶层函数形式直接为与kt文件中
  2. 以类成员位于类体中(所定义类体不是被扩展方法的类体,否则扩展方法也就失去了意义);扩展方法中既可以调用被扩展类的成员方法、属性也可以调用定义所在类的成员

如:

	class A{
		fun bar()=println("A的Bar()")

	}

	class B{
		fun foo()=println("B的foo()")
		fun bar()=println("B的bar()") 
		fun A.info(){
			foo()
			[email protected]()//将调用B的bar()
			bar()//将调用A的bar()


		}

	}

定义在类中的扩展方法,即使被扩展类成员,有是定义所在类成员,所以可以访问两者的成员(属性、方法),可以省略"this"

但是可能出现这种情况:定义类和被扩展类中有相同签名的方法,如果在扩展方法中调用相同签名的方法,系统优先调用被扩展类中的那个方法被,这时如果要调用定义所在类的那个方法就必须借助"this@定义所在类名"。

Kotlin中的this支持用"this@类名"形式,限制this代表哪个类

1.4、java中调用扩展方法

首先需要明白一点的是:

Kotlin编译器本身支持静态解析(根据调用对象、方法名找到对应的扩展方法,转为函数调用);java编译器本身不支持静态解析,需要程序员手动做好静态解析;

Kotlin:将List.info()扩展方法定义在Test.kt文件中

	fun List.info(){

		.......

	}

调用:list.info()既可

java中调用:

	1.首先创建List对象

		ArrayList list=new ArrayList();

	2.前面我们说了定义的顶级函数会变成函数"所在文件+Kt"(TestKt.class)类的静态方法,所以调用扩展方法就是"文件对应类.扩展方法(扩展类对象,参数)“

		TestKt.info(list)

1.5、可空类型扩展方法

可空类型允许为null,因此在定义扩展方法时,需要在扩展方法中判断处理为null时的情况

2、匿名扩展函数

匿名函数顾明思意:没有函数名.所谓匿名扩展方法其实就是带接受者的匿名函数;接受者就是".()"前面的类型

	var info=fun Int.():Int{


	}

匿名扩展函数类型是:Int.()->Int,这里Int就是被扩展类类型即在普通函数类型前添加了一个接受者类型限定

3、扩展属性

扩展属性不能有幕后字段,因此对扩展属性的限制要求即没有幕后字段属性要求:

  1. 扩展属性不能有初始值
  2. 只读属性必须重写getter方法,读写属性必须重写getter、setter方法
  3. getter、setter方法中不能使用field关键字显示访问幕后字段

和扩展方法一样,扩展属性本质是重写getter、setter方法也可以使用泛型函数的形式来定义扩展属性:

val <T> List<T>.lastIndex:Int
		get()=size-1

猜你喜欢

转载自blog.csdn.net/Leslie_LN/article/details/82895852
今日推荐