코틀린 내부 클래스
- 중첩(Nested)클래스
- 이너(Inner)클래스
종류 | 역할 |
정적 클래스 (static class) |
static 키워드를 가지며 외부 클래스를 인스턴스화 하지않고 바로 사용 가능한 클래스 (주로 빌더 클래스에 이용) 중첩 클래스(nested class): 객체 생성 없이 사용 가능 |
멤버 클래스 (member class) |
인스턴스 클래스로도 불리며 외부 클래스의 필드나 메서드와 연동하는 내부 클래스 이너 클래스(inner class): 필드나 메서드와 연동하는 내부 클래스로 inner 키워드가 필요 |
지역 클래스 (local class) |
초기화 블록이나 메서드 내의 블록에서만 유효한 클래스 지역 클래스(local class): 클래스의 선언이 블록에 있다면 지역 클래스 |
익명 클래스 (anonymous class) |
이름이 없고 주로 일회용 객체를 인스턴스화하면서 오버라이드 메서드를 구현하는 내부 클래스. 가독성이 떨어지는 단점 익명 객체(anonymous object): 이름이 없고 주로 일회용 객체를 사용하기 위해 object 키워드를 통해 선언 |
** 코틀린에서는 object키워드가 붙으면 보통 익명클래스..
// 자바의 멤버(이너) 클래스
class A {
...
class B {
... // 외부 클래스 A의 필드에 접근 가능
}
}
// 자바의 정적 클래스
class A {
static class B { // 정적 클래스를 위해 static
// 키워드를 사용
...
}
}
// 코틀린의 이너 클래스
class A {
...
inner class B { // 자바와 달리 inner 키워드 필요
... // 외부 클래스 A의 필드에 접근 가능
}
}
// 정적 클래스처럼 사용한 코틀린의 중첩 클래스
class A {
class B { // 코틀린에서는 아무 키워드가 없는 클래스는
// 중첩 클래스이며 정적 클래스처럼 사용
... // 외부 클래스 A의 프로퍼티, 메서드에
//접근할 수 없음
}
}
중첩 클래스(Nested class)
- 코틀린에서 중첩 클래스는 기본적으로 정적(static) 클래스처럼 다뤄짐
package com.example.pp223
class Outer {
val ov = 5
class Nested {
val nv = 10
fun greeting() = "[Nested] Hello! $nv" // 외부의 ov에는 접근 불가
}
fun outside() {
val msg = Nested().greeting() // Outer객체 생성 없이 중첩 클래스의 메서드 접근
println("[Outer]: $msg, ${Nested().nv}") // 중첩 클래스의 프로퍼티 접근
}
}
fun main() {
// static처럼 Outer의 객체 생성 없이 Nested 객체를 생성하여 사용 가능
val output = Outer.Nested().greeting()
println(output)
// Outer.outside() // 에러 Outer 객체 생성 필요
val outer = Outer()
outer.outside()
}
중첩 클래스 사용 예제
ov는 인스턴스형
중첩 클래스인 class Nested는 static형
fun outside()는 인스턴스형
package com.example.pp224
class Outer {
class Nested {
fun accessOuter() { // 컴패니언 객체는 접근할 수 있음
println(country)
getSomething()
}
}
companion object { // 컴패니언 객체는 static처름 접근 가능
const val country = "Korea"
fun getSomething() = println("Get Something...")
}
}
fun main() {
val output = Outer.Nested().accessOuter()
println(output)
}
코틀린 중첩 클래스에서 바깥 클래스 접근 예제
바깥 클래스에서 접근하는 방법 : Outer클래스가 컴패니언 객체를 가지고 있을 때 접근 가능
이너 클래스
- 특별한 키워드인 inner를 사용해 선언된 내부 클래스
- 이너 클래스는 바깥 클래스의 멤버들에 접근 가능
- 바깥 클래스의 private 멤버도 접근이 가능
package com.example.pp226
class Smartphone(val model: String) {
private val cpu = "Exynos"
inner class ExternalStorage(val size: Int) {
fun getInfo() = "${model}: Installed on $cpu with ${size}Gb" // 바깥 클래스의 프로퍼티 접근
}
}
fun main() {
val mySdcard = Smartphone("S7").ExternalStorage(32)
println(mySdcard.getInfo())
}
이너 클래스의 바깥 클래스의 멤버 접근 예제
지역 클래스
- 특정 메서드의 블록이나 init 블록과 같이 블록 범위에서만 유효한 클래스
- 블록 범위를 벗어나면 더 이상 사용되지 않음
package com.example.pp228
class Smartphone(val model: String) {
private val cpu = "Exynos"
inner class ExternalStorage(val size: Int) {
fun getInfo() = "${model}: Installed on $cpu with ${size}Gb" // 바깥 클래스의 프로퍼티 접근
}
fun powerOn(): String {
class Led(val color: String) { // 지역 클래스 선언
fun blink(): String = "Blinking $color on $model" // 외부의 프로퍼티는 접근 가능
}
val powerStatus = Led("Red") // 여기에서 지역 클래스가 사용됨
return powerStatus.blink()
} // powerOn() 블록 끝
}
fun main() {
val mySdcard = Smartphone("S7").ExternalStorage(32)
println(mySdcard.getInfo())
val myphone = Smartphone("Note9")
myphone.ExternalStorage(128)
println(myphone.powerOn())
}
메서드에 지역 클래스 적용 예제
익명 객체
- 자바에서는 익명 이너 클래스라는 것을 제공해 일회성으로 객체를 생성해 사용
- 코틀린에서는 object 키워드를 사용하는 익명 객체로 같은 기능을 수행
package com.example.pp230
interface Switcher { // 인터페이스 선언
fun on(): String
}
class Smartphone(val model: String) {
private val cpu = "Exynos"
inner class ExternalStorage(val size: Int) {
fun getInfo() = "${model}: Installed on $cpu with ${size}Gb" // 바깥 클래스의 프로퍼티 접근
}
fun powerOn(): String {
class Led(val color: String) { // 지역 클래스 선언
fun blink(): String = "Blinking $color on $model" // 외부의 프로퍼티는 접근 가능
}
val powerStatus = Led("Red") // 여기에서 지역 클래스가 사용됨
val powerSwitch = object : Switcher { // 익명 객체를 사용해 Switcher의 on()을 구현
override fun on(): String {
return powerStatus.blink()
}
} // 익명(object) 객체 블록의 끝
return powerSwitch.on() // 익명 객체의 메서드 사용
} // powerOn() 블록 끝
}
fun main() {
val mySdcard = Smartphone("S7").ExternalStorage(32)
println(mySdcard.getInfo())
val myphone = Smartphone("Note9")
myphone.ExternalStorage(128)
println(myphone.powerOn())
}
익명 객체를 위한 인터페이스 예제
연산자 오버로딩
- 연산자에 여러 가지 다른 의미의 작동을 부여
- 코틀린에서는 특정 연산자의 역할을 함수로 정의
- operator 키워드를 사용해 정의
- a+b : a.plus(b)
- a-b : a.minus(b)
- a*b : a.times(b)
- a/b : a.div(b)
- a%b : a.rem(b)
- a..b : a.rangeTo(b)
package com.example.pp233
class Point(var x: Int = 0, var y: Int = 10) {
// plus 함수의 연산자 오버로딩
operator fun plus(p: Point) : Point {
return Point(x + p.x, y + p.y)
}
}
fun main() {
val p1 = Point(3, -8)
val p2 = Point(2, 9)
var point = Point()
point = p1 + p2 // Point 객체의 + 연산이 가능하게 됨
println("point = (${point.x}, ${point.y})")
}
연산자 오버로딩 예제
호출 연산자(invoke operator)
- 함수 호출을 돕는데 사용
package com.example.pp235
class Manager {
operator fun invoke(value: String) {
println(value)
}
}
fun main() {
val manager = Manager()
manager("Do something for me!") // manager.invoke("...")형태로 호출되며 invoke가 생략되었다.
}
호출연산자 예제
인덱스 연산자(indexed access operator)
- getter/setter를 다루기 위한 대괄호([]) 연산자 제공
- a[i] : a.get(i)
- a[i, j] : a.get(i, j)
- a[i] = b : a.set(i, b)
- a[i, j] = b : a.set(i, j, b)
단항 연산자(부호)
- 먼저 a의 자료형을 결정하고 매개변수 없이 각 연산자에 대한 함수를 호출한 다음 연산된 결과를 반환
- +a : a.unaryPlus()
- -a : a.unaryMinus()
- !a : a.not()
package com.example.pp237
data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)
fun main() {
val point = Point(10, 20)
println(-point) // 단일 연산자에 의해 (-10, -20) 값을 바꿈
}
포함 범위 연산자
- in 연산자는 반복문에 사용해 특정 객체의 반복에 사용/ 포함 여부 판단
- a in b : b.contains(a)
- a !in b : !b.contains(a)
if (i in 1..10) { // 1 <= i && i <= 10 와 동일
println(i)
}
for (i in 1..4) {
print(i) // "1234" 출력
}
할당 연산자(augmented assignments)
- a += b : a.plusAssign(b)
- a -= b : a.minusAssign(b)
- a *= b : a.timesAssign(b)
- a /= b : a.divAssign(b)
- a %= b : a.remAssign(b)
동등성 연산자(equality and inequality)
- a == b -> a?.equals(b) ?: (b === null)
- a != b -> !(a?.equals(b) ?: (b === null))
비교 연산자(comparison)
- a > b : a.compareTo(b) > 0
- a < b : a.compareTo(b) < 0
- a >= b : a.compareTo(b) >= 0
- a <= b : a.compareTo(b) <= 0
** 양이면 1, 음이면 -1, 동등이면 0
'Kotlin' 카테고리의 다른 글
Kotlin #11 : 제네릭, 배열 230223 (0) | 2023.02.24 |
---|---|
Kotlin #9 : 객체, 데이터 클래스, Companion 객체, object, singleton, 추상 클래스, 인터페이스 230222 (0) | 2023.02.23 |
Kotlin #8 : 코틀린의 프로퍼티, 자바의 필드, 지연 초기화, lazy, 위임 230220 (0) | 2023.02.22 |
Kotlin #7 : 정보 은닉 캡슐화 (연관, 의존, 집합, 구성) 230220 (0) | 2023.02.20 |
Kotlin #6 : 상속과 클래스 230217 (0) | 2023.02.20 |
댓글