1.コンセプト
クラスコードを変更せずkotlin支持体、クラスを動的属性(拡張属性)とメソッド(拡張メソッド)を加えます。
2.拡張メソッド
(コンパイル時に)静的に行うための分析方法を拡張し、分析方法のメンバーは、動的(実行時)を行います。
(1)構文
「クラス名」を追加するための関数の定義関数は、前に定義されている、それは、クラスのクラス名に対応する機能拡張方法です。
fun main(args: Array<String>) {
val extensionClass = ExtensionClass()
//调用拓展方法
extensionClass.test()
}
//定义一个空类
class ExtensionClass
//为该空类定义一个拓展方法test()方法
fun ExtensionClass.test() = println("我是ExtensionClass的拓展方法")
(2)優先順位方式のメンバー
拡張メソッドは、クラスメソッドのメンバーを持つクラスに拡張されている場合は名前とパラメータを、のようなクラスのオブジェクトは、このメソッドを呼び出すときに、呼び出しは、メソッドのメンバーになります。
fun main(args: Array<String>) {
val extension = ExtensionTest()
//此处调用的会是成员方法
extension.test()
}
class ExtensionTest {
fun test() = print("成员方法")
}
//该方法不会被调用
fun ExtensionTest.test() = println("扩展方法")
(3)(文字列として)システムクラスのメソッドを拡張するために追加されます
fun main(args: Array<String>) {
val str = "123456"
//调用String的拓展方法
println(str.lastIndex())
}
//为String定义一个拓展方法
fun String.lastIndex() = length - 1
(4)を達成する原理を拡張
Javaはクラスがソースコードを変更し、クラスを再コンパイルしない限り、あなたが動的に、メソッド、プロパティ、クラスを追加することはできません、静的な言語です。
kotlin拡張属性は、この方法は、実際に拡張したクラスを変更していないときに動的にクラスのメンバに追加しているように見える、kotlin本質は、ある関数の定義、オブジェクトはクラスのコール拡張メソッドを拡張した場合、 kotlinを行う静的解像度を、関数呼び出しを拡張するために解決静的関数を呼び出します。
静的解像度:拡張機能を見つけるために呼び出すオブジェクト、メソッド名に応じては、関数呼び出しに変換します。
(2)str.lastIndex()メソッドの処理を行う:
①(文字列を見つける。)STR型を確認してください。
定義されている場合②直接、文字列lastIndexの()メンバメソッドを定義するかどうかをコンパイラをチェックします。
StringはlastIndexの()メソッドを定義されていない場合③、プログラムを探すkotlinがある有望なStringクラスは、拡張メソッドの定義場合は、拡張メソッドを実行します(それが楽しいString.lastIndexは、()があるかどうか、である)lastIndexの()メソッドを拡張します;
④どちらも拡張メソッドを定義していないlastIndexの()メンバメソッドは、コンパイラは自然に通過しない定義されました。
(5)拡張メソッド静的解像度の点に注意を喚起する
静的コールが拡張メソッドはコンパイル時に実行されるため、親と子のクラスは、拡張メソッドは、同じ名前を拡張しているので、もし、引用の種類は、親クラスの下にある、親クラスの拡張メソッドを呼び出します。
/**
* 拓展属性、方法
*/
fun main(args: Array<String>) {
val father : ExtensionTest = ExtensionTest()
father.test()//调用父类扩展方法
val child1 : ExtensionTest = ExtensionSubTest()
child1.test()//引用类型为父类类型,编译时静态调用的还是父类的扩展方法
val child2 : ExtensionSubTest = ExtensionSubTest()
child2.test()//此时才是调用子类的扩展方法
}
/**
* 父类
*/
open class ExtensionTest
/**
* 子类
*/
class ExtensionSubTest : ExtensionTest()
/**
* 父类扩展一个test方法
*/
fun ExtensionTest.test() = println("父类扩展方法")
/**
* 子类扩展一个test方法
*/
fun ExtensionSubTest.test() = println("子类扩展方法")
(6)null許容型エクステンションの方法(実施例を拡張する方法に等しいです)
kotlin膨張null許容型拡張メソッド例えば、ヌルメソッドを呼び出すことができる可能にします。
fun main(args: Array<String>) {
val a: Any? = null
val b: Any? = null
println(a.equals(b))
}
fun Any?.equals(any: Any?): Boolean = this != null && any != null && any.equals(this)
3.拡張属性
(1)コンセプト
kotlin拡張属性はないフィールド(出願)の背後にある拡張属性を取得、設定で実施される方法を、追加することにより、動的クラスを可能にします。
拡張属性が本当にクラスにプロパティを追加していない、クラスは取得のみで計算として記述することができ、メソッドの属性を設定します。
リミット:①拡張プロパティは初期値を持つことができません。②キーワードに提出されていないアクセスの背後に拡張属性フィールド、メソッドを提供する必要があり、varが取得提供し、方法を設定する必要があり得る③val。
(2)拡張属性を定義します
fun main(args: Array<String>) {
val extensionTest = ExtensionTest("a", "b")
println(extensionTest.param1)//a
println(extensionTest.param2)//b
println(extensionTest.extensionParam)//a-b
}
/**
* 定义一个类,包含属性param1、属性param2
*/
class ExtensionTest(var param1: String, var param2: String)
/**
* 为该类扩展属性extensionParam
*/
var ExtensionTest.extensionParam: String
set(value) {
param1 = "param1$value"
param1 = "param2$value"
}
get() = "$param1-$param2"
クラスメンバーで定義された4方法が伸びます
拡張されたクラス定義のための他の方法、属性、拡張メソッドは、クラスのクラスオブジェクトコール拡張メソッドにクラスによって拡張することができます。
クラスに属するクラスのメンバーを定義するために拡張拡張され、従って呼び出しクラスメンバー(これは省略することができる)を直接拡張メソッドを拡張され、それはここでクラスに位置しているので、ので、直接ここクラスのメンバーを呼び出すことができ。
fun main(args: Array<String>) {
val extensionTest = ExtensionTest()
val extensionTest2 = ExtensionTest2()
extensionTest2.info(extensionTest)
}
/**
* 定义一个类包含test方法
*/
class ExtensionTest {
fun test() = println("ExtensionTest的test方法")
}
/**
* 定义一个类包含test方法,包含ExtensionTest的一个扩展方法
*/
class ExtensionTest2 {
val a = "a"
fun test() = println("ExtensionTest2的test方法")
fun ExtensionTest.func() {
println(a)//调用扩展类的成员
test()//调用被扩展类的成员,相当于this.test()
[email protected]()//同名的需要用this@类名的方式来调用
}
fun info(extensionTest: ExtensionTest) {
extensionTest.func()
}
}
バンド広がり関数匿名の受信者
(1)コンセプト
拡張メソッド(楽しいメソッド名のクラス名()。)匿名メソッド名を削除するには、受信機と広がり関数と呼ばれ、受信機があるクラス自体のような形、:)楽しいのInt(:.のInt 。
fun main(args: Array<String>) {
val extensionTest = ExtensionTest()
println(extensionTest.noNameExtensionFun("向带接收者的匿名函数传入的参数"))//使用匿名扩展函数
}
/**
* 定义一个空类
*/
class ExtensionTest
/**
* 为空类定义一个带接收者的匿名扩展函数
*/
var noNameExtensionFun = fun ExtensionTest.(param: String): String {
println(param)
return "我是来自带接收者的匿名扩展函数的返回值"
}
匿名の受信者と(2)関数型の分布関数
- >文字列ExtensionTest(文字列):正常な機能と、匿名の拡張方法は、関数型、関数型(1)などを有しています。
レシピエントと匿名拡張関数とラムダ式(3)
受信機は、コンテキスト・タイプから推測することができる場合は、ラムダ式を使用することができます
fun main(args: Array<String>) {
test {
println(it)
"匿名扩展函数返回值"
}
}
/**
* 定义一个空类
*/
class ExtensionTest
/**
* 定义一个函数,形参为ExtensionTest.(String) -> String类型,相当于同时为ExtensionTest类扩展了一个匿名扩展函数
*/
fun test(fn: ExtensionTest.(String) -> String) {
val extensionTest = ExtensionTest()
println("调用匿名扩展函数:${extensionTest.fn("匿名扩展函数传入形参")}")
}
6.拡張使用シナリオ
あなたはクラスのプロパティのいくつかは、継承などの手段によって達成されなければならない拡張したい場合は、プログラムの柔軟性を高めることに大きく展開し、Javaの、直接の構文を使用してkotlinを動的それが簡単にいくつかのツールの方法を整理するために拡張することができます。
fun main(args: Array<String>) {
"打印日志".log()
}
/**
* 为String字符串添加一个打印日志的扩展方法
*/
fun String.log() {
println(this)
}