본문 바로가기
언어/Kotlin

[Kotlin 문법 종합] - 메소드, 클래스

by 젼젼39 2024. 3. 5.

 

 

1. 메소드

    : 특정 동작을 하는 소스코드에 이름을 붙임     //ex. sum

    (+) 추상화, 간결해짐
    (+) 코드의 재사용성

fun 메소드이름(변수명:자료형, 변수명:자료형 ....) : 반환자료형{
	//소스코드 로직
} 	//( ) 안의 것들은 매개변수 parameter

//반환자료형이 없는 경우  Unit 또는 생략 가능 (ex. println)
fun myInfo(): Unit {
	//코드
}

        (예시 - 점수 입력 후 등급 출력하는 코드)

fun main(){
    var myScore = readLine()!!.toInt()
    
    var myRank = turnRank(myScore)
    //println("rank : ${myRank}")
}

fun turnRank(score:Int) : String{
	return when(score){
    	in 90..100 -> return 'A' 	//범위표기법 주목
    	in 80..89 -> return 'B'
        in 70..79 -> return 'C'
        else -> return 'D'
    }
}

// when에 in 90..100 이런식으로 쓰지 않고
// if에 구간별로 나눈 건
// Kotlin 컨벤션을 따르지 않은 형태...라는데
// 뭔말일까

 

// 동일한 함수의 다양한 작성법

fun sum(a : Int, b : Int): Int{
    var sum = a + b
    return sum
}
fun sum(a : Int, b : Int) : Int{
    return a + b
}
fun sum(a : Int, b : Int) : Int = a + b
fun sum(a : Int, b : Int) = a + b

 

// 매개변수의 일부만 전달 시 자동으로 기본값 입력하기

fun exampleAdd(name : String, address : String = "default"){
    //address로 넘어오는 값이 없으면 자동으로 "default" 입력함
}
fun main(){
    exampleCode(x = 100, y = 200)
    exampleCode(x = 100)
}

fun exampleCode(x:Int, y:Int = 300, z:Int = 150){
     println(x+y+z)
}

//450
//550

 

// 가변 인자 Variable Argument

fun main(){
    varargExample(1,2,3,4)
    varargExample(1,2,3,4,5)
}

fun varargExample(vararg counts: Int){ 		//counts를 가변인자로 지정, int형 배열
    for (num in counts){
        print("$num")
    }
    println("")
}


//1 2 3 4
//1 2 3 4 5

 

 

2. 클래스

1. 객체지향 프로그래밍

    : 객체(object) 단위로 처리함

  •     java, c++ 등

    *키워드
        (1) 클래스
        (2) 추상화
        (3) 캡슐화 Encapsulation
                        : 외부의 잘못된 사용으로 객체가 손상되는 것을 막음
        (4) 상속 Inheritance
                        : 코드 재사용 가능, 일괄 업데이트로 관리 타임 짧아짐
        (5) 다형성 Polymorphism
                        : 사용방법이 동일하지만 실행결과가 다양하게 나옴

// 절차지향 프로그래밍 : c, 포트란, 알골 등
// 함수형 프로그래밍 : 스칼라, R 등

 

2. 클래스

    : 프로그램의 각 요소별 설계도

    - 정보와 행위(메소드) 작성함
    - 하나의 파일에 하나 이상의 클래스 존재 가능

class 클래스이름{
    정보 1 		//자료형 명시해주기. (생성자 있으면 안해도 ㄱㅊ)
    정보 2 		//string이면 ""
    
    행위 1
    행위 2
}

1. 데이터 클래스 data class

    : 정보(프로퍼티)만 가지고 있는 클래스

    - 기본 생성자에 1개 이상의 매개변수가 변수나 상수로 존재해야 함
    - abstract, open, sealed, inner를 사용할 수 없음

    *자동으로 만들어지는 메소드들
        (1) hashCode() : 객체 구분을 위한 고유값 리턴. 동일하다면 동일한 정숫값을 생성함
        (2) equals() : 동일한 객체인지 비교해 참/거짓을 리턴함
        (3) copy() : 현 객체의 모든 정보를 복사 후 새 객체를 리턴함.
                           (특정 프로퍼티 = "~" 한 경우 빌더 없이 특정 프로퍼티만 변경해 객체 복사함)
        (4) toString() : 데이터 객체를 읽기 편한 문자열로 반환
        (5) getXXX() / setXXX(매개변수) : 변수의 값 리턴 혹은 설정
        (6) //객체 디스트럭처링하기 -> val (가져올 프로퍼티1, _(안가져올경우) = 가져올 해당 객체)
        (7) //개별적으로 프로퍼티 가져오기 -> val email2 = 해당객체.component2()

data class 클래스이름 {
	정보1
	정보2
}

                 + 중첩 클래스 (nested)

                  : 객체 생성 없이 중첩 클래스의 메서드 접근 가능 ( 원래 클래스.Nested.함수명() )

                    //특정 메서드의 블록이나 init블록 등에 있지 않은 것! (<- 지역 클래스)

                  - 중첩된 Nested 클래스는 바로 바깥 클래스의 멤버에는 접근 불가능
                  - but 바로 바깥 클래스가 컴패니언 객체를 갖고있으면 접근 가능 (static처럼 접근 가능하니까)

 

2. 실드 클래스 sealed class

    : 클래스 상속과 관련, 상속받을 수 있는 클래스들을 미리 정의

    - 객체를 만들 수 없음 (상속은 가능, 생성자도 기본적으로는 private)

    (+) 무분별한 상속을 방지
    (+) 컴파일 시점에 생성할 수 있는 자식을 알 수 있어 다형성 구현

sealed class 부모클래스 {
    class 자식클래스1 : 부모클래스생성자
    class 자식클래스2 : 부모클래스생성자
}


// 1. 실드 클래스 선언 방법 첫번째 스타일
sealed class Result {
    open class Success(val message: String): Result()
    class Error(val code: Int, val message: String): Result()
}

class Status: Result() // 실드 클래스 상속은 같은 파일에서만
class Inside: Result.Success("Status") // 내부 클래스 상속

// 2. 실드 클래스 선언 방법 두번째 스타일
/*
sealed class Result

open class Success(val message: String): Result()
class Error(val code: Int, message: String): Result()

class Status: Result()
class Inside: Success("Status")
*/


fun main() {
    // Success에 대한 객체 생성
    val result = Result.Success("Good!")
    val msg = eval(result)
    println(msg)
}

// 상태를 검사하기 위한 함수
fun eval(result: Result): String = when(result) {
    is Status -> "in progress"
    is Result.Success -> result.message
    is Result.Error -> result.message
    // 모든 조건을 가지므로 else 가 필요 없다
}

Good!

 

3. 오브젝트 클래스 object class

    : 프로그램 실행과 동시에 인스턴스화 (java의 static 대신 사용하는 키워드)
            //프로그램 메모리에 바로 올라가서 사용 가능하게 됨    

    //관련해서는 아래 글 이어서 읽기

2024.03.06 - [언어/Kotlin] - [Kotlin 문법 종합] - Single-expression function, 싱글턴 (@@질문하기)

 

[Kotlin 문법 종합] - Single-expression function, 싱글턴 (@@질문하기)

1. Single-expression function : 람다식을 이용해 메소드를 간결하게 정리 가능 * 람다식 구조 : 다른 함수의 인자로 넘김 / 함수의 결과값으로 반환 / 변수에 저장 하는 함수 {매개변수1, 매개변수2... ->

sugapowderjj.tistory.com

2024.03.15 - [언어/Kotlin] - [Kotlin 공부] object와 싱글톤, object와 compaion

 

[Kotlin 공부] object와 싱글톤, object와 compaion

dd

sugapowderjj.tistory.com

 

    * 익명 객체와 다름! 익명객체는 아래 v

interface Switcher{
    fun on(): String
}

class Smartphone(val model: String){
    
    fun powerOn(): String{
        class Led(Val color: String){
            fun blink(): Stirng = "Blinking $color on $model"
        }
        val powerStatus = Led("Red")
        val powerSwitch = object : Switcher{ 	//익명 객체를 사용해 switcher의 on() 구현
            override fun on(): String{
                return powerStatus.blink()
            }
        }//익명(object)객체 블록의 끝
    }
}

    // 인터페이스의 메소드 구현을 익명 객체 안에서 해도 됨 (밖에 따로 만든 걸 받아와도 ㄱㅊ)

 

 

4. 열거 클래스 enum class 

    : 여러 곳에 동일한 상수를 정의하는 등의 경우에 용이한 관리를 위해 사용

    - 다양한 자료형을 다루지는 못함. 자료형이 동일한 상수를 나열함
    - 프로퍼티 혹은 메서드를 담을 수 있음
    - 각 상수의 값은 () 매개변수를 통해 초기화할 수 있음

enum class DayOfWeek(val num: Int){
    MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4),
    FRIDAY(5), SATURDAY(6), SUNDAY(7)
}

fun main(){
	val day=DayOfWeek.MONDAY 		//Monday의 값 읽기
    when(day.num){
        1,2,3,4,5 -> println("Weekday")
        else -> println("weekend")
    }
}

Weekday
enum class Color(val r:Int, val g:Int, val b: Int){
    RED(255,0,0), ORANGE(255,165,0), YELLOW(255,255,0),
    GREEN(0,255,0), BLUE(0,0,255), INDIGO(75,0,130),
    VIOLET(238,130,238); 		//세미콜론으로 끝 알림
    
    fun rgb() = (r*256 + g) * 256 + b 	//메서드 포함
}

fun getColor(color : Color) = when (color){
    Color.RED -> color.name 	//이름 가져옴 RED
    Color.ORANGE -> color.ordinal 	//순서 번호 : 1
    Color.YELLOW -> color.toString() //문자열 변환
    Color.GREEN -> color 	//기본값 (문자열) GREEN
    Color.BLUE -> color.r 	//r값
    Color.INDIGO -> color.g
    Color.VIOLET -> color.rgb() 	//연산 결과
    
}

fun main(){
    println(Color.BLUE.rgb())
    println(getColor(Color.RED))
}

255
interface Score {
    fun getScore(): Int
}

enum class MemberType(var prio: String) : Score {
    NORMAL("Thrid") {
        override fun getScore(): Int  = 100 	//구현된 메서드
    },
    SILVER("Second") {
        override fun getScore(): Int  = 500
    },
    GOLD("First") {
        override fun getScore(): Int  = 1500
    }
}

fun main() {
    println(MemberType.NORMAL.getScore())
    
    println(MemberType.GOLD)
    
    println(MemberType.valueOf("SILVER"))
    
    println(MemberType.SILVER.prio)

    for (grade in MemberType.values()) { 	//모든 값을 가져오는 반복문
        println("grade.name = ${grade.name}, prio = ${grade.prio}")

    }
}


100

GOLD

SILVER

Second

grade.name = NORMAL, prio = Thrid
grade.name = SILVER, prio = Second
grade.name = GOLD, prio = First

//prio는 내가 바꿔 불러도 됨. numnum 이런것도 가능

    - Comparable 인터페이스를 구현하는 추상 클래스                       //추가 공부 필요...

enum class 클래스1 {
    C, JAVA, KOTLIN
}

enum class 클래스2(val code:Int){
    C(10),
    JAVA(20),
    KOTLIN(30)
}

fun main(){
    println(클래스1.C.toString()) 		//C
    println(클래스2.KOTLIN.code) 		//30
    println(클래스2.KOTLIN.name) 		//KOTLIN
}

code: 클래스2 enum 클래스의 생성자에 정의됨. 각 enum 인스턴스에 대해 별도로 값 설정
name: enum 클래스의 속성, enum 상수의 이름을 문자열로 반환