Android 확장함수 범위지정함수
업데이트:
카테고리: Android
/확장함수
어떤 클래스의 멤버 메서드인 것처럼 호출, 클래스 밖에 선언된 함수
기존의 클래스는 건들이지 않고 추가로 함수를 제작함 ⇒ 캡슐화는 깨지지 않음
fun string.lastChar(): Char = this.get(this.length - 1)
string
: 타입this
: 수신받는 객체
open class Shape
class Rectangle: Shape()
fun Shape.getName() = "shape"
fun Rectangle.getName() = "rectangle"
fun printClassName(s: Shape) {
println(s.getName())
}
printClassName(Rectangle()) // shape
확장 함수는 정적 바인딩되기 때문에 컴파일 이후, 값이 변하지 않는다.
범위지정함수
제공된 람다식을 써서 객체에서 이런 함수를 호출하면 임시 범위가 형성된다. 이 범위에선 이름없이 객체에 접근할 수 있다.
작성하는 이유는 범위함수를 사용해서 코드를 작성한 경우가 가독성이 더 좋기 때문에
receiver
: 수신객체
block
: 람다식
-
with → Non-Null한 수신 객체, 결과가 필요하지 않은 경우
<T.R>.with(receiver: T, block: T.() -> R): R { return receiver.block() } val person = Person("Jone", 30) val result = with(person) { // 별도의 참조없이도 객체 내부의 변수와 함수를 사용할 수 있음 // 람다식의 결과를 반환함 val Introduction = "내 이름은 $name이고 나이는 $age입니다." Introduction.length // 리턴값 }
-
also → 객체를 사용하지 않음, 객체 속성을 변경하지 않고 사용 / 사이드 이펙트, 데이터 유효성 검사
<T>T.also(block: (T) -> Unit): T { block(this) return this } val list = listOf<String>("one", "two").also { it -> // 반환값은 로직을 돈 결과가 아니라 원본 데이터라는 점 println("반환 목록 $it") }
-
apply → 람다 내부에서 객체 함수를 사용하지 않을 때, 객체 자신은 반환시 사용 / 객체 초기화에 주로 사용
<T>T.apply (block: T.() -> Unit) : T { block() return this } val person = Person().apply { // Person 객체 내부에 있는 변수를 초기화하거나 변경 name = "John" age = 30 say("Hello") }
-
let → 저장된 값이 null이 아닌 경우에 코드를 실행해야 될 때 사용
<T.R>T.let(block:(T) -> R) R { return block(this) }
-
run → 어떤 값 계산 / 여러 개의 지역 변수 범위 제한
<T.R>T.run(block: T.() -> R): R { return block() } // also와 다르게 로직을 실행한 결과가 반환된다. val message = "Hello World" val result = message.run { val uppercased = toUpperCase() // == this.toUpperCase() "$uppercased length: ${length}" // 람다 결과 }