Kotlin

[Android] [Kotlin] 클래스

Design-loving front-end engineer 2021. 8. 30. 16:45

클래스

Primary Constructor

class Person constructor(value: String) {
}

◽  헤더처럼 class 키워드와 같은 위치에 작성

◽  조건에 따라 constructor 생략 가능

class Person(value: String) {
    init {
        Log.d("class", "생성자로부터 전달받은 값은 ${value}입니다.")
    }
}

◽  클래스의 생성자가 호출되면 init 블록의 코드가 실행되고, init 블록에서는 생성자를 통해 넘어온 파라미터에 접근

class Person(val value: String) {
    fun process() {
        print(value)
    }
}

◽  파라미터 앞에 val을 붙여주면 클래스 스코프 전체에서 해당 파라미터를 사용할 수 있다.

Secondary Constructor

class Kotlin {
    constructor (value: String) {
        Log.d("class", "생성자로부터 전달받은 값은 ${value}입니다.")
    }
    constructor (value: Int) {
        Log.d("class", "생성자로부터 전달받은 값은 ${value}입니다.")
    }
    constructor (value1: Int, value2: String) {
        Log.d("class", "생성자로부터 전달받은 값은 ${value1}, ${value2}입니다.")
    }
}

◽  constructor 키워드를 마치 함수처럼 클래스 스코프 안에 직접 작성

◽  init 블록을 작성하지 않고 constructor 다음에 괄호를 붙여서 코드를 작성

사용 방법

◽  생성자 호출 순서 : init 블록(primary constructor) -> constructor 블록 안의 코드

var kotlin = Kotlin()

◽  Kotlin() 인스턴스를 kotlin 변수에 넣어둔다.

 

오브젝트

✔  클래스를 인스턴스화 하지 않아도 블록 안의 프로퍼티와 메서드를 호출해서 사용

✔  자바의 static과 같은 역할

✔  클래스와 다르게 앱 전체에 1개만 생성된다.

object Pig {
    var name: String = "Pinky"
    fun printName() {
        Log.d("class", "Pig의 이름은 ${name}입니다.")
    }
}

Pig.name = "Mikey"
Pig.printName()

companion object

✔  일반 클래스에 object 기능을 추가

class Pig {
    companion object {
        var name: String = "None"
        fun printName() {
            Log.d("class", "Pig의 이름은 ${name}입니다.")
        }
    }
    fun walk() {
        Log.d("class", "Pig가 걸어갑니다.")
    }
}

// companion object 안의 코드 사용
Pig.name = "Linda"
Pig.printName()

// companion object 밖의 코드 사용
val cutePig = Pig()
cutePig.walk()

 

데이터 클래스

✔  값의 저장 용도

✔  class 앞에 data 키워드

✔  파라미터 앞에 var 또는 val 생략 불가

data class UserData(val name: String, var age: Int)
var userData = UserData("Michael", "21")

userData.name = "Sindy"  // (x) val
userData.age = 18  // (o) var

Log.d("DataClass", "DataUser는 ${dataUser.toString()}")
// --> DataUser는 DataUser(name=Michael, age=21)

◽  일반 클래스에서 toString() 메서드를 사용하면 인스턴스의 주소 값을 반환하지만, 데이터 클래스는 값을 반환

 

상속과 확장

✔  부모 클래스는 open 키워드로 만들어야 자식 클래스에서 사용 가능

✔  콜론을 이용해서 상속할 부모 클래스를 지정

✔  상속은 부모의 인스턴스를 자식이 갖는 과정이기 때문에 반드시 부모의 생성자를 호출해야 한다.

open class 상속될 부모 클래스 {
    // 코드
}

class 자식 클래스: 부모 클래스() {
    // 코드
}

[ 생성자 파라미터가 있는 클래스 상속 ]

open class 부모 클래스(value: String) {
    // 코드
}

class 자식 클래스(value: String): 부모 클래스(value) {  // 파라미터를 전달
    // 코드
}

[ 부모 클래스에 세컨더리 생성자가 있을 경우 ]

class CustomView: View {
    constructor(ctx: Context): super(ctx)
    constructor(ctx: Context, attrs: AttributeSet): super(ctx, attrs)
}

◽  부모 클래스명 다음에 오는 괄호를 생략

 

[ 부모 클래스의 프로퍼티와 메서드 사용하기 ]

open class Parent {
    var hello: String = "안녕하세요."
    fun sayHello() {
        Log.d("inheritance", "${hello}")
    }
}

class Child: Parent() {
    fun myHello() {
        hello = "Hello!"
        sayHello()
    }
}

// "Hello!"

 

오버라이드

✔  상속받은 부모 클래스의 프로퍼티와 메서드 중에 자식 클래스에서 다른 용도로 사용하기 위한 도구

✔  부모 클래스에서 open 키워드로 선언한 프로퍼티나 메서드만 오버라이드 가능

open class BaseClass {
    open var opened: String = "I am"
    open fun opened() {
    }
    fun notOpened() {
    }
}

class ChildClass: BaseClass() {
    override var opened: String = "I am"
    override fun opened() {
    }
    override fun notOpened() {  // 오버라이드 불가능
    }
}

익스텐션

✔  이미 만들어져 있는 클래스에 메서드를 추가

✔  실제 클래스의 코드가 변경되는 것은 아님

fun testStringExtension() {
    var original = "Hello"
    var added = " Guys~"
    Log.d("Extension", "added를 더한 값은 ${original.plus(added)}입니다.")
}

fun String.plus(word: String): String {
    return this + word
}