[TIL] Kotlin 문법 실습 (함수, 클래스)

Yanus·2024년 3월 29일

함수

함수는 기능구현의 단위이며 호출시 블럭내 코드를 수행하게 된다.
함수의 구조는 다음과 같다.

fun 함수이름(파라미터 이름: 파라미터 타입): 리턴 타입 {
}

fun plus(x: Int, y: Int): Int {
    return x + y
}
  1. 입력 파라미터 O, 리턴값 O
fun 함수이름(파라미터 이름: 파라미터 타입) {
}

fun printSum(x: Int, y: Int) {
    println("x + y = ${x + y}")
}
  1. 입력 파라미터 O, 리턴값 X
fun 함수이름(): 리턴 타입 {
}

fun getPi(): Double {
    return 3.14
}
  1. 입력 파라미터 X, 리턴값 O
fun 함수이름() {
}

fun hello() {
    println("hello world")
}
  1. 입력 파라미터 X, 리턴값 X

Default parameter

파라미터가 있는 함수를 사용할 때 Default parameter를 설정하면
입력값이 없는 경우에도 기본값으로 동작을 할 수 있게 해준다.


fun showInfo(name: String, age: Int = 30, weight: Double = 70.5) {
    println("이름은 ${name}")
    println("나이는 ${age}")
    println("몸무게는 ${weight}")
}

두번째 default parameter: age = 30
세번째 default parameter: weight = 70.5
기본값들을 설정하면 다음과 같이 함수를 호출해서 사용할 수 있다.

showInfo("Michael", 29, 65.5)
showInfo("Michael")
showInfo("Michael", weight = 67.5)

클래스

클래스는 변수와 함수의 모음이다.
클래스의 변수를 프로퍼티, 클래스 함수를 메소드라고 부른다.

class Student {
    var name: String = "홍길동"
    fun printName() {
        println("이름은 ${name}입니다.")
    }
}
    var kim = Student()
    kim.printName()    

Student라는 클래스를 만들고나서 생성자를 호출하여 변수에 담는다. (인스턴스화)
인스턴스 생성후 메소드를 호출할 수 있다.
프로퍼티는 default 값으로 저장되어있는 것을 확인할 수 있다.

class Student {
    constructor(name: String, id: Int) {
        this.name = name
        this.id = id
    }

    var name: String = "홍길동"
    var id: Int = 0
    fun printInfo() {
        println("이름은 ${name}입니다.")
        println("학번은 ${id}입니다.")
    }
}    
    var kim = Student("김민수", 1234)
    kim.printInfo()

생성자를 constructor로 정의하면 인스턴스 생성과 동시에 프로퍼티를 원하는 값으로 초기화가 가능하다.
this는 자신이 생성할 인스턴스를 가리키며 이를 통해 프로퍼티에 접근할 수 있다.

오브젝트

클래스가 생성자를 호출해야 메모리를 할당받는 것과 달리
오브젝트는 프로그램 시작과 동시에 메모리를 할당받는다.(static 클래스)
그래서 오브젝트 이름자체로 프로퍼티, 메소드에 접근한다.

object Person {
    var name: String = "홍길동"
    fun printName() {
        println("이름은 ${name}입니다.")
    }
}
Person.printName()

오브젝트이름으로 메소드 호출이 가능하다.(생성자 불필요)

컴패니언 오브젝트

클래스 전체를 static으로 사용하지 않고
부분적으로만 static으로 사용하고 싶은 경우가 있다.

이때는 클래스 내부 companion object 선언을 하면 해당 부분만 static 영역으로 사용할 수 있다. (static 프로퍼티, static 메소드)

class Person {
    companion object {
        var name: String = "홍길동"
        fun printName() {
            println("이름은 ${name}입니다.")
        }
    }
    fun greeting() {
        println("안녕하세요")
    }
}
    var kim = Person()
    Person.name = "김민수"
    Person.printName()
    kim.greeting()

클래스 메소드는 인스턴스(kim)을 통해서 접근하지만
static 프로퍼티, static 메소드는 클래스 이름(Person)을 통해 접근한다.

데이터 클래스

데이터 클래스는 값의 저장용도로 사용한다.

data class UserData(val name: String, var age: Int)
    var user = UserData("Michael", 20)
    user.age = 30
    println("이름:${user.name}, 나이:${user.age}")
    println("${user.toString()}")

일반적으로 코드 블럭을 사용하지 않고 간단하게 사용하는 경우가 많다.

상속

상속은 코드를 재사용하며 체계적으로 관리할 수 있는 방법이다.
자식 클래스를 만들때 부모 클래스를 지정하면 부모클래스의 메소드와 프로퍼티를 사용할 수 있다.

open class Person
{
    var name: String = "홍길동"
    fun showInfo()
    {
        println("이름은 ${name}")
    }
}

class Student : Person()
{
    var id: Int = 0
    fun showId()
    {
        println("학번은 ${id}")
    }
}
    var kim = Student()
    kim.name = "김민수"
    kim.id = 1234
    kim.showInfo()
    kim.showId()

부모클래스는 open 키워드를 붙여 생성한다.
class 자식클래스이름 : 부모클래스이름()
과 같이 부모클래스를 지정한다.
자식 클래스 인스턴스를 생성하면 부모클래스의 프로퍼티와 메소드를 가지고 있는 것을 확인할 수 있다.

오버라이드

open class Person {
    var name: String = "홍길동"
    open fun showInfo() {
        println("이름은 ${name}")
    }
}

class Student : Person() {
    var id: Int = 0
    override fun showInfo() {
        println("이름은 ${name}")
        println("학번은 ${id}")
    }
}
    var kim = Student()
    kim.name = "김민수"
    kim.id = 1234
    kim.showInfo()

부모클래스의 프로퍼티 또는 메소드를 open 키워드를 붙이고
자식클래스의 프로퍼티 또는 메소드는 override 키워드를 붙임으로써 재정의를 할 수 있다.
자식 클래스 인스턴스의 메소드를 호출하면 재정의된 함수가 호출되는 것을 확인할 수 있다.

추상화

추상화는 설계도면이라고 생각하면 좋다.
인터페이스, 추상클래스로 큰 틀을 설계한 후에 이를 상속받은 클래스에서 구체적인 내용을 구현한다.

인터페이스

interface Animal {
    var name: String
    fun move()
}

class Bird : Animal {
    override var name: String = "새"
    override fun move() {
        println("${name}가 날아서 이동합니다.")
    }
}
    var bird = Bird()
    bird.move()

인터페이스를 상속받은 클래스는 프로퍼티와 메소드를 모두 오버라이드해서 구현해야한다.

추상클래스

abstract class Animal {
    abstract var name: String
    abstract fun move()
    fun walk() {
        println("${name}가 걷습니다.")
    }
}

class Bird : Animal() {
    override var name: String = "새"
    override fun move() {
        println("${name}가 날아서 이동합니다.")
    }
}
    var bird = Bird()
    bird.walk()

실제로 구현한 코드가 포함이 된다면 인터페이스 대신에 추상클래스를 사용한다. 그외 내용은 인터페이스와 동일하다.

익스텐션

익스텐션은 미리 만들어져 있는 클래스에 메소드를 추가하는 개념이다.

fun String.customPlus(word: String): String {
    return this + word
}
    var org = "Hello"
    var added = "World"

    println("결과: ${org.customPlus(added)}")

기존에 있는 클래스 String에 customPlus 새로운 메소드가 추가된 것을 확인할 수 있다.

profile
양우성

0개의 댓글