코 틀린 확장 방법, 특성

1. 개념

클래스 코드를 수정하지 않고 코 틀린 지원 클래스 동적 특성 (확장 된 속성) 및 방법 (확장 법)에 추가한다.

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) 달성하기위한 원리를 확장

자바 클래스의 소스 코드를 수정하고 클래스를 다시 컴파일하지 않는 동적, 메서드, 속성 클래스를 추가 할 수 없습니다, 정적 언어입니다.

코 틀린는 방법이 실제로 확장 한 클래스를 수정하지 않을 때 본질은 코 틀린 동적 클래스 멤버에 추가 될 것으로 보인다, 확장 속성을 함수의 정의 , 객체가 클래스 호출 확장 방법을 확장, 코 틀린은 수행 정적 해상도를 , 함수 호출을 확장하기로 결심 정적 함수를 호출합니다.

정적 해상도 : 호출하는 객체에 따라, 메소드 이름은 함수 호출로 변환 확장 기능을 찾을 수 있습니다.

(2) str.lastIndex () 메서드는 과정 수행으로 :
① 확인 STR 유형 (문자열 찾기);

문자열이 정의는 lastIndex 있는지 확인 ② () 멤버 메소드 정의하면 컴파일러 직접;

문자열이는 lastIndex () 메소드를 정의되지 않은 경우 ③, 프로그램을 찾기 코 틀린 것은 유망한 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) 널 타입 확장하는 방법 (예를 확장하는 방법을 동일)

코 틀린 팽창 형 널 연장 방법은 허용 널 메소드가 호출 할 수있다.

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) 개념

코 틀린 확장 속성은 확장 된 속성이 없습니다 (출원) 분야 뒤에, 설정 구현하는 방법을 얻을 추가하여 동적 클래스를 할 수 있습니다.

확장 속성은 정말 클래스에 속성을 추가하지 않은 클래스 만, 가져 오기에 의해 계산 방법의 속성을 설정이라고 할 수있다.

제한 :; 키워드에 제출하지 액세스 뒤 ② 확장 된 속성 필드, ① 확장 속성이 초기 값을 가질 수 없습니다 방법을 제공해야 얻을 ③val을, VAR는 get 및 set 메소드를 제공해야합니다.

(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) 개념

확장 메서드 (. 재미있는 방법 이름 클래스 이름 ()) 익명 메소드 이름이 수신기 확산 함수를 호출 제거, 수신기는 클래스 자체 재미 지능 () :. 지능 : 모양, .

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 문자열 (String)을 정상 기능으로 익명의 확장 방법은 함수 타입, 함수 타입 (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. 확장 사용 시나리오

당신이 직접 구문은 동적으로 쉽게 몇 가지 도구 방법을 정리하기 위해 확장 할 수 있습니다 사용하여 코 틀린 클래스의 속성 중 일부는 상속 등의 방법으로 달성되어야 확장 할 경우 프로그램의 유연성, 자바 증가 크게 확장합니다.

fun main(args: Array<String>) {
    "打印日志".log()
}

/**
 * 为String字符串添加一个打印日志的扩展方法
 */
fun String.log() {
    println(this)
}

추천

출처www.cnblogs.com/nicolas2019/p/10932131.html