1.  오브젝트  Object

👩🏻‍💻  오브젝트 object를 사용하면 클래스를 생성자로 인스턴스화 하지 않아도 블록 안의 프로퍼티와 메서드를 호출해서 사용할 수 있다.  ➡️ 자바의 static과 같은 역할
👩🏻‍💻  object 코드 블록 안의 프로퍼티와 메서드는 클래스명에 점 연산자를 붙여서 생성자 없이 직접 호출
👩🏻‍💻  주의할 점은 클래스명을 그대로 사용하기 때문에 호출하는 클래스명의 첫 글자가 대문자


1) 컴패니언 오브젝트


  👾  일반 클래스에 object 기능을 추가하기 위해서 사용
  👾  클래스 코드 안에 companion object 블록으로 감싸주면 생성 과정 없이 오브젝트처럼 사용할 수 있음

object Cat {
    var name: String ="pinky"
    fun printName() {
        println("Cat의 이름은 ${name}입니다.")
    }
}

class Dog {
    companion object {
        var name: String = "None"
        fun printName() {
            println("Dog 이름은 ${name}입니다.")
        }
    }
    fun walk() {
        println("Dog가 뛰어갑니다.")
    }
}

fun main() {
    Cat.name = "mikey"
    Cat.printName() // Cat의 이름은 mikey 입니다.

    // companion object 안의 코드 사용하기
    Dog.name = "Linda"
    Dog.printName() // Dog 이름은 Linda 입니다.
    //Dog.walk() companion object 밖에 선언된 메소드는 사용하지 못함

    // companion object 밖의 코드 사용하기
    val dog = Dog()
    dog.walk() // Dog가 뛰어갑니다.

}

 


2.  데이터 클래스

👩🏻‍💻  코틀린은 간단한 값의 저장 용도로 데이터 클래스 data class를 제공

data class 클래스 이름 (val 파라미터1: 타입, var 파라미터2: 타입)


  ✏️  데이터 클래스를 정의할 때 class 앞에 data 키워드를 사용해야 하고, 생성자 파라미터 앞에 입력하는 var 또는 val 키워드를 생략할 수 없음
  ✏️  생성하는 코드는 일반 클래스와 동일하게 작성

fun main() {
    // 정의 - 주로 코드 블록(클래스 스코프)을 사용하지 않고 간단하게 작성.
    data class UserData(val name: String, var age: Int)

    // 생성 - 일반 class의 생성자 함수를 호출하는 것과 동일
    val userData = UserData("Michael", 21)

    //userData.name = "Cindy" // val로 선언되었기 때문에 변경 불가능

    userData.age = 19 // var로 선언되었기 때문에 변경 가능
}

1) toString() 메소드와 copy() 메소드


  👾  일반 클래스에서 toString() 메소드를 호출하면 인스턴스의 주소값을 반환하지만, 데이터 클래스는 값을 반환하기 때문에 실제 값을 모니터링 할 때 좋음

    println("userData는 ${userData}") // userData는 UserData(name=Michael, age=19)
    println(userData.toString()) // UserData(name=Michael, age=19)

 

  👾  copy() 메소드로 간단하게 값을 복사할 수 있음

    var newData: UserData = userData.copy()

 

  👾  이처럼 클래스와 사용법이 동일하지만 주로 네트워크를 통해 데이터를 주고 받거나, 혹은 로컬 앱의 데이터베이스에서 데이터를 다루기 위한 용도로 사용

 

데이터 클래스는 toString(), copy()와 같은 메소드를 자동으로 만들어줌
    * toString() : 객체에 포함되어 있는 데이터를 출력하여 볼 수 있음. 생성자에 포함된 프로퍼티만 출력.
    * copy() : 객체의 속성들을 복사하여 반환하는 메소드이며 인수로 받은 프로퍼티만 해당 값으로 바뀌어 복사해줌
fun main() {

    data class Memo(val title: String, val content: String, var isDone: Boolean)
    val memo1 = Memo("마트 가기", "계란, 우유, 빵", false)

    val memo2 = memo1.copy(content="칫솔, 과자") // content 프로퍼티만 변경
    println(memo1.toString()) // Memo(title=마트 가기, content=계란, 우유, 빵, isDone=false)
    println(memo2.toString()) // Memo(title=마트 가기, content=칫솔, 과자, isDone=false)

}

 

 


3.  클래스의 상속과 확장

1) 클래스의 상속

 

👩🏻‍💻  상속을 사용하면 부모 클래스의 프로퍼티를 마치 내 클래스의 일부처럼 사용할 수 있음

      상속을 사용하는 예를 들면 안드로이드는 Activity라는 클래스가 미리 만들어져 있고, 이 Activity 클래스 내부에는 글자를 쓰는 기능, 그림을 그리는 기능, 화면에 새로운 창을 보여주는 기능이 미리 정의되어 있음. 상속이 있기에 이런 기능을 직접 구현하지 않고 Activity 클래스를 상속받아 약간의 코드만 추가하면 앱에 필요한 기능을 추가할 수 있음.

 

👩🏻‍💻  코틀린에서 클래스를 상속받으려면 부모 클래스에 open 키워드를 추가해야 함

       ✓ 상속을 받을 자식 클래스에서는 콜론을 이용해서 상속할 부모 클래스를 지정 .다음에 괄호를 입력해서 꼭 부모의 생성자를 호출

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

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


👩🏻‍💻  메소드도 자식 클래스에서 오버라이딩하려면 부모 클래스의 메소드에 open 키워드를 추가

fun main() {

    open class Flower {
        open fun waterFlower() {
            println("water flower")
        }
    }
    // 콜론 : 을 이용해 상속을 나타내면 됨
    class Rose: Flower() {
        override fun waterFlower() {
            super.waterFlower()
            println("Rose is water flower")
        }
    }

    val rose = Rose() // 객체 생성
    rose.waterFlower() // Rose is water flower

}

 



A. 생성자가 있는 클래스의 상속


👩🏻‍💻  상속될 부모 클래스의 생성자에 파라미터가 있다면 자식 클래스를 통해 값을 전달할 수 있음

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

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


   👾 부모 클래스에 세컨더리 생성자가 있다면, 자식 클래스의 세컨더리 생성자에서 super 키워드로 부모 클래스에 전달할 수 있음
   👾 부모 클래스의 세컨더리 생성자를 이용하는 경우에는 부모 클래스명 다음에 오는 괄호를 생략

 


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


👩🏻‍💻  부모 클래스에서 정의된 프로퍼티와 메서드는 내 것처럼 사용할 수 있음

    open class Parent {
        var hello: String = "안녕하세요"
        fun sayHello() {
            println(hello)
        }
    }

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

    val child = Child()
    child.myHello() // Hello

2) 익스텐션


코틀린은 클래스, 메서드, 프로퍼티에 대해 익스텐션 extensions 을 지원
이미 만들어져 있는 클래스에 다음과 같은 형태로 추가할 수 있음

    fun 클래스.확장할 메서드() {    // 코드    }*

 

    👾  상속이 미리 만들어져 있는 클래스를 가져다 쓰는 개념이라면 익스텐션은 미리 만들어져 있는 클래스에 메서드를 넣는 개념
           ✓ 자신이 만든 클래스에 사용하기 보다는 이미 컴파일되어 있는 클래스에 메서드를 추가하기 위한 용도로 사용
    👾  실제 클래스의 코드가 변경되는 것은 아니며 단지 실행 시에 점 연산자로 호출해서 사용할 수 있도록 해줌

아래 코드는 기본 클래스인 String에 plus 메서드를 확장하는 코드
test 함수에 선언한 original에 문자열을 입력했기 때문에 original은 String의 익스텐션 메서드인 plus를 호출해서 사용
fun main() {

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

    fun testStringExtension() {
        val original = "Hello"
        val added = "Guys~"

        println("added를 더한 값은 ${original.addText(added)}입니다.")
    }

    testStringExtension() // added를 더한 값은 HelloGuys~입니다.

}

 

 

[ 내용 참고 : IT 학원 강의 ]


1.  클래스  Class

간단하게 보면 클래스는 변수와 함수의 모음. 그룹화할 수 있는 변수와 함수를 한 군데에 모아 놓고 사용하기 쉽게 이름을 붙여놓은 것을 클래스 라고 이해하면 된다.


1) 코틀린에서 사용되는 클래스의 기본 구조

    class 클래스 이름 {
       var 변수
       fun 함수() {
           코드
       }
   }


 2) 클래스 코드 작성하기


👻  클래스를 만들기 위해서는 먼저 클래스의 이름을 정하고, 이름 앞에 class 키워드를 붙여서 만들 수 있음
👻  클래스 이름 다음에는 클래스의 범위를 지정하는 중괄호({}) 가 있어야 함
        ➡️  이 중괄호를 스코프 Scope라고 하는데, 클래스에서 사용했기 때문에 클래스 스코프라고 함

 class 클래스 이름 {  // 클래스 스코프 class scope   }


    ✓  '몇몇 예외'는 있지만 대부분의 코드는 클래스 스코프 안에 작성.

 

👻  작성된 클래스를 사용하기 위해서는 생성자라고 불리는 함수가 호출되어야 함

👻  코틀린은 프라이머리 primary와 세컨더리 Secondary 2개의 생성자를 제공


2. 생성자

1) 프라이머리 생성자

 class Person 프라이머리 생성자() { }


함수에 있는 코드를 실행하려면 함수를 호출해야 함. 클래스도 마찬가지로 클래스를 사용한다는 것은 곧 클래스라는 이름으로 묶여 있는 코드를 실행하는 것이기 때문에 함수 형태로 제공되는 생성자를 호출해야지만 클래스가 실행

  ⚡️ 프라이머리 Primary 생성자는 마치 클래스의 헤더처럼 사용할 수 있으며, constructor 키워드를 사용해서 정의하는데 조건에 따라 생략할 수 있음
  ⚡️ 프라이머리 생성자도 결국 함수이기 때문에 파라미터를 사용할 수 있음

   class Person constructor(value: String) {    // 코드   }

 

  📍 생성자에 접근 제한자나 다른 옵션이 없다면 constructor 키워드를 생략할 수 있음

  class Person(value: String) {   // 코드   }

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

fun main() {
    class Person1 constructor (str: String) {
        init {
            println("생성자로부터 전달받은 값은 ${str}입니다.")
        }
    }
    var person1 = Person1("1") // 생성자로부터 전달받은 값은 1입니다.
}

 

  📍   init 초기화 작업이 필요하지 않으면 init 블록을 작성하지 않아도 됨
          ➡️ 대신 파라미터로 전달된 값을 사용하기 위해서는 파라미터 앞에 변수 키워드인 val을 붙여주면 클래스 스코프 전체에서 해당 파라미터를 사용할 수 있음

fun main() {
    class Person2(val str: String) {
        fun process() {
            println("생성자로 생성된 변수의 값은 ${str}입니다.")
        }
    }

    var person2 = Person2("2")
    person2.process() // 생성자로 생성된 변수의 값은 2입니다.
}

    

   ✓ 생성자 파라미터 앞에 var도 사용할 수 있으나, 읽기 전용인 val을 사용하는 것을 권장


 2) 세컨더리 생성자


세컨더리 Secondary 생성자는 constructor 키워드를 마치 함수처럼 클래스 스코프 안에 직접 작성할 수 있음
그리고 다음과 같이 init 블럭을 작성하지 않고 constructor 다음에 괄호를 붙여서 코드를 작성할 수 있음

    class Person3 {
        constructor(str: String) {
            println("생성자로부터 전달받은 값은 ${str}입니다.")
        }
    }

 

  📍 세컨더리 생성자는 파라미터의 개수, 또는 파라미터의 타입이 다르면 (오버로딩) 여러 개를 중복해서 만들 수 있음

fun main() {
    class Sample {
        constructor(str: String) {
            println("생성자로부터 전달받은 값은 ${str}입니다.")
        }

        constructor(value: Int) {
            println("생성자로부터 전달받은 값은 ${value}입니다.")
        }

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

    val sample = Sample(1,"2") // 생성자로부터 전달받은 값은 1, 2입니다.
}

3) Default 생성자


생성자를 작성하지 않을 경우 파라미터가 없는 프라이머리 생성자가 하나 있는 것과 동일

fun main() {
    class Student { // 생성자를 작성하지 않아도 기본 생성자가 동작.
        init {
            // 기본 생성자가 없더라도 초기화가 필요하면 여기에 코드를 작성.
        }
    }
}

 


 3.  클래스의 사용

클래스명()

 

👻  클래스의 이름에 괄호를 붙여서 클래스의 생성자를 호출. constructor 키워드를 호출하지 않음
    ⚡️ 아무런 파라미터 없이 클래스명에 괄호에 붙여주면 생성자가 호출되면서 init 블록 안의 코드가 자동으로 실행
    ⚡️ 세컨더리 생성자의 경우 init 블록이 먼저 실행되고 constructor 블록 안의 코드가 실행

👻  코틀린에서는 자바보다 클래스를 좀 더 편하게 정의할 수 있음
    ⚡️ 자바의 보일러 플레이트 코드가 삭제되고 필요한 코드들만 작성하면 되도록 바뀜
         * 보일러 플레이트 코드 : 상용구 코드. 변형이 거의 또는 전혀 없이 여러 위치에서 반복되는 코드 문구.

fun main() {
   
    class Car(val color: String)

    /*
    객체를 생성. 자바에서는 new 키워드를 사용했지만, 코틀린에서는 필요가 없음.
     */
    var car = Car("blue") // 객체 생성

}

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1. 셋  Set

👩🏻‍💻  셋은 중복을 허용하지 않는 리스트로 리스트와 유사한 구조이지만 인덱스로 조회할 수 없고, get() 메서드도 지원하지 않음

👩🏻‍💻  같은 값을 추가하더라도 해당 값은 하나만 저장
👩🏻‍💻  리스트와 마찬가지로 읽기 전용 셋과 읽기 쓰기 모두 가능한 셋, 총 두가지를 제공
       ➡️  각각 setOf(), mutableSetOf() 함수로 객체를 생성

    // 읽기 전용 셋
    val immutableSet = setOf(1, 1, 2, 2, 2, 3, 3)
    println(immutableSet) // [1, 2, 3]

 1) 빈 셋으로 초기화하고 값 입력하기

    var set = mutableSetOf<String>()
    set.add("JAN")
    set.add("FEB")
    set.add("MAR")
    set.add("JAN") // 셋은 중복을 허용하지 않기 때문에 동일한 값은 입력되지 않음

2) 셋 사용하기


  👾  인덱스로 조회하는 메서드가 없기 때문에 특정 위치의 값을 직접 사용할 수 없음

    println("Set 전체 출력 : ${set}") // Set 전체 출력 : [JAN, FEB, MAR]

3) 삭제하기


  👾  값이 중복되지 않기 때문에 값으로 직접 조회해서 삭제 할 수 있음

    set.remove("FEB")
    println("Set 전체 출력 : ${set}") // Set 전체 출력 : [JAN, MAR]

  👾  함수사용 결과는 요소 삭제나 추가가 정상적으로 이루어졌을 때 true,

         정상적으로 이루어지지 않았을 때 false로 boolean 형 결과로 나옴

    val mutableSet = mutableSetOf(1, 1, 2, 2, 2, 3, 3)
    println(mutableSet.add(100)) // true
    println(mutableSet.add(3)) // false

2.  맵  Map

👩🏻‍💻  맵은 키 Key와 값 Value의 쌍으로 입력되는 컬렉션
👩🏻‍💻  맵의 키는 리스트의 인덱스와 비슷한데 맵에는 키를 직접 입력하고 중복되지 않도록 해야 함

    ⚡️  제네릭으로 키와 값의 데이터 타입을 지정해서 맵을 생성
    ⚡️  맵의 요소는 Pair(A, B)를 사용하는 데 이는 A to B로도 표현할 수 있음

// 읽기 전용 맵
val immutableMap = mapOf("name" to "tom", "age" to 28, "age" to 20, "height" to 170)
println(immutableMap) // {name=tom, age=20, height=170} 중복이 있을 경우 마지막 키값이 저장됨

1) 맵 생성하기


  👾  키와 값의 데이터 타입을 모두 String으로 사용

 var map = mutableMapOf<String, String>()

2) 값 추가하기


  👾  값을 추가하기 위해 제공되는 put 메서드에 키와 값을 입력

    map.put("키1", "값1")
    map.put("키2", "값2")
    map.put("키3", "값3")
    println(map) // {키1=값1, 키2=값2, 키3=값3}


3) 맵 사용하기


  👾  get 메서드에 키를 직접 입력해서 값을 사용할 수 있음

println("map에 입력된 키1의 값은 ${map.get("키1")}입니다.") // map에 입력된 키1의 값은 값1입니다.

 4) 맵 수정하기


  👾  put() 메서드를 사용할 때 동일한 키를 가진 값이 있으면 키는 유지된 채로 값만 수정

map.put("키2", "수정한 값")
map["키2"] = "수정한 값"
println("map에 입력된 키2의 값은 ${map.get("키2")}입니다.") 
// map에 입력된 키2의 값은 수정한 값입니다.

5) 맵 삭제하기


  👾  remove() 메서드에 키를 입력해 값을 삭제할 수 있음

map.remove("키1")

// 없는 값을 불러오면 null 값이 출력됨
println("map에 입력된 키1의 값은 ${map.get("키1")}입니다.") 
// map에 입력된 키1의 값은 null입니다.

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1.  컬렉션

자바에서 리스트 List, 셋 Set, 맵 Map 등 여러 자료 구조를 사용하는데, 코틀린에서도 이러한 컬렉션을 모두 사용할 수 있을 뿐만 아니라 몇 가지 편리한 함수를 추가로 제공. 또한 코틀린은 컬렉션을 읽기 전용 immutable 컬렉션읽기-쓰기 mutable 컬렉션으로 크게 두 가지로 나눔


1) 리스트 List


  👻 리스트 List는 저장되는 데이터에 인덱스를 부여한 컬렉션이며 중복된 값을 입력할 수 있음
  👻 코틀린에서 동적으로 리스트를 사용하기 위해서는 리스트 자료형 앞에 뮤터블 Mutable 이라는 접두어 prefix가 붙음
        💫  접두어가 있는 리스트도 있지만 잘 사용하지 않기 때문에 항상 mutableList, mutableMap, mutableSet을 사용

 

 뮤터블과 이뮤터블


프로그래밍 언어에서 뮤터블은 변할 수 있는 데이터 타입을 가르키는 용어변수로는 var이 뮤터블
그리고 반대 개념인 이뮤터블 Immutable이 있는데 이것은 val과 같이 변할 수 없는 데이터 타입을 가르키는 용어.

  ⚡️ 코틀린은 컬렉션 데이터 타입을 설계할 때 모두 이뮤터블로 설계
  ⚡️ 기본 컬렉션인 리스트, 맵, 셋은 모두 한 번 입력된 값을 바꿀 수 없음
  ⚡️ 컬렉션의 원래 용도인 동적 배열로 사용하기 위해서는 뮤터블로 만들어진 데이터 타입을 사용해야 함

 

읽기 전용 리스트는 listOf() 함수를 사용
읽기 쓰기 모두 가능한 리스트는 mutableListOf() 함수를 사용
    // 이뮤터블
    val numList = listOf(1, 2, 3)
    println(numList[1]) // 2
    // numList[0] = 10    // error
   // 뮤터블
   val mutableList = mutableListOf("MON", "TUE", "WED") 
    // 3개의 값을 가진 크기가 3인 동적 배열 리스트가 생성

2) 리스트에 값 추가하기 : add


  👻  mutableList 변수에 add 메서드를 사용해서 값을 추가
  👻  값이 추가되면서 동적으로 리스트의 공간이 자동으로 증가

        mutableList.add("THU") 
        // 입력될 위치인 인덱스를 따로 지정해주지 않아도 입력되는 순서대로 인덱스가 지정.
        println(mutableList) 
        // [MON, TUE, WED, THU]

3) 리스트에 입력된 값 사용하기 : get


  👻  입력할 때와는 다르게 사용할 때는 인덱스를 지정해서 몇 번째 값을 꺼낼 것인지 명시

        var variable = mutableList.get(1) // 두 번째 값을 변수에 저장
        variable = mutableList[1]
        println(variable) // TUE

4) 리스트 값 수정하기 : set


  👻  특정 인덱스 값을 수정

        mutableList.set(1, "수정할 값") // 두 번째 값을 수정
        println(mutableList) // [MON, 수정할 값, WED, THU]
        mutableList[1] = "수정할 값" // 두 번째 값을 수정.

5) 리스트에 입력된 값 제거하기 : removeAt


  👻  리스트에 입력된 값의 인덱스를 지정해서 삭제

        println(mutableList.get(1)) // 수정할 값
        mutableList.removeAt(1) // 두 번째 값을 삭제
        // 두 번째 값을 삭제하면 세 번째 값부터 인덱스가 하나씩 감소하면서 빈자리의 인덱스로 이동
        println(mutableList.get(1)) // WED

6) 빈 리스트 사용하기


  👻  아무것도 없는 빈 리스트를 생성하면 앞으로 데이터 타입을 알 수 없기 때문에 값의 타입을 추론할 수 없음
  👻  빈 컬렉션의 경우 앞에서처럼 '데이터타입of'만으로는 생성되지 않고 데이터 타입을 직접적으로 알려주는 방법을 사용해야 함

var 변수명 = mutableListOf<컬렉션에 입력될 값의 타입>()
var stringList = mutableLisfOf<String>()
        // 생성
        val stringList = mutableListOf<String>() // 문자열로 된 빈 컬렉션을 생성

        stringList.add("월")
        stringList.add("화")
        println(stringList[1]) // 화

7) 컬렉션 개수 가져오기 : size


  👻  size 프로퍼티를 사용하면 컬렉션의 개수를 가져올 수 있음

        println("stringList에는 ${stringList.size}개의 값이 있습니다.")
        // stringList에는 2개의 값이 있습니다.

 


예제


    문자열을 저장할 수 있는 List 객체를 생성하고 여기에 "a", "b", "c", "d", "e"를 저장한 후 이것을 출력하는 프로그램을 생성
    출력 예:  [a, b, c, d, e]

    1. 뮤터블  2. 이뮤터블 두 케이스 다 작성

fun main() {

    val charList = listOf("a", "b", "c", "d", "e") 
    println(charList) // [a, b, c, d, e]

    val mutableList = mutableListOf<String>()
    // val mutableList: MutableList<String> = mutableListOf()
    mutableList.add("a")
    mutableList.add("b")
    mutableList.add("c")
    mutableList.add("d")
    mutableList.add("e")

    println(mutableList) // [a, b, c, d, e]
}

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1.  함수  function

🐰  함수는 fun으로 정의하고 반환값이 있는 함수는 내부에서 return으로 값을 반환
🐰  함수를 정의할 때 입력값을 기술한 것을 '파라미터'

    fun 함수이름 (파라미터 이름 : 타입) : 반환타입 {
        return 값
    }


  🥕  함수의 괄호 안에 입력되는 '파라미터 이름 : 타입'에 따라, 함수를 호출할 때 괄호 안에 값을 넣어서 전달하는데
        이 때 입력되는 값의 타입은 함수에 정의된 파라미터 타입과 동일하게 입력해야 함

 

1) 함수의 정의

 

 반환값과 입력값이 있는 함수의 정의


    ✏️  Int 타입의 x라는 입력 파라미터를 갖는 함수 square()를 정의

fun square(x: Int): Int {
    return x * x
}
// square() 함수가 호출되면 입력값을 제곱해서 호출한 측으로 반환하고 실행이 종류.

반환값이 없는 함수의 정의 

 

    ✏️  반환값 없이 입력값을 받아서 출력하는 함수 printSum() 함수를 정의. 함수가 호출되면 결과값을 출력하고 실행이 종료

fun printSum(x: Int, y: Int) {
    println("x + y = ${x + y}")
}

입력값 없이 반환값만 있는 함수의 정의
fun getPi(): Double {
    return 3.14
}


 2) 함수의 사용(호출)


🐰  함수의 사용은 이름 뒤에 괄호를 붙여서 명령어를 실행하는 형태

함수명(값)    

 

    🥕  괄호를 붙이지 않으면 함수의 코드가 실행되지 않고 마치 값처럼 인식

 

반환값과 입력값이 있는 함수의 호출


   ✏️  파라미터에 전달할 값을 입력하고 반환값은 대입 연산자(=)로 변수에 담은 후 사용

fun main() {
    var squareResult = square(30)
    println("30의 제곱은 ${squareResult}입니다.") // 30의 제곱은 900입니다.
    println("40의 제곱은 ${square(40)}입니다.") // 40의 제곱은 1600입니다.
}

반환값이 없는 함수의 호출


    ✏️  반환값이 없으면 대입 연산자(=)를 사용하지 않고 바로 호출해서 실행

fun main() {
    printSum(3, 5) // x + y = 8
}

입력값이 없는 함수의 호출


    ✏️  입력값이 없다면 괄호만으로 실행하고 결과값을 받을 수 있음

fun main() {

    val PI = getPi()
    println("지름이 10인 원의 둘레는 ${PI}입니다.") // 지름이 10인 원의 둘레는 3.14입니다.

}

 2.  함수 파라미터의 정의

🐰  함수에 입력되는 파라미터는 마치 변수를 정의하듯이 '이름 : 타입'의 형태로 정의
       ➡️  여러 개의 파라미터가 정의될 경우는 콤마로 구분
🐰  코틀린에서 함수 파라미터를 통해 입력되는 모든 값은 변하지 않는 immutable
🐰  코틀린에서의 함수 파라미터는 모두 읽기 전용 키워드 val이 생략된 형태

 fun 함수이름((val 생략) name1: String, name2: Int, name3: Double) {실행코드} 

 

 

1) 파라미터의 기본값 정의와 호출


    🥕  파라미터는 정의할 때 등호(=)를 사용해서 기본값을 설정할 수 있음

fun 함수이름 (name1: String, name2: Int = 157, name3: Double = 34.5) {실행코드}
fun newFun(name: String, age: Int = 29, weight: Double = 65.5) {
        // name = "tom"; // Val cannot be reassigned
        println("name의 값은 ${name}입니다.")
        println("age의 값은 ${age}입니다.")
        println("weight의 값은 ${weight}입니다.")
}

// 정의된 newFun() 함수를 호출할 때 기본값이 없는 첫 번째 파라미터에만 값을 입력하면
// 두 번째와 세 번째 파라미터에는 설정한 기본값이 자동으로 입력.
    
    newFun("Hello")
    /*
    name의 값은 Hello입니다.
    age의 값은 29입니다.
    weight의 값은 65.5입니다.
     */


2)  파라미터 이름으로 값을 입력하기


    🥕  함수에 정의된 파라미터가 많을 경우 입력하는 값의 의미가 명확하지 않을 때가 있음
    🥕  이럴 경우 순서와 상관 없이 정의된 파라미터 이름을 지정해서 직접 값을 입력할 수 있음

fun main() {

    newFun("Michael", weight=67.5)
    /*
     name의 값은 Michael입니다.
     age의 값은 29입니다.
     weight의 값은 67.5입니다.
     */

}

 


응용 예제

 

   📍 login() 메서드와 logout() 메서드를 선언
        login() 메서드를 호출할 때는 매개값으로 id와 passwd를 제공하고, logout() 메서드는 id만 매개값으로 제공

       1) login() 메서드는 매개값 id가 "admin", 매개값 password가 "1234"일 경우에만 true 로 리턴하고

           그외의 값일 경우에는 false를 리턴
       2) logout() 메서드는 "admin 아이디가 로그아웃 되었습니다"가 출력

fun main() {

    print("아이디를 입력해주세요. >> ")
    val id = readln()
    print("비밀번호를 입력해주세요. >> ")
    val password = readln()

    val result = login(id = id, password = password)
    if (result) {
        println("로그인 되었습니다.")
        logout(id)
    } else {
        println("id 또는 password가 올바르지 않습니다.")
    }

}

fun login(id:String, password: String): Boolean {
    return id == "admin" && password == "1234"
}

fun logout(id: String) {
    println("$id 아이디가 로그아웃 되었습니다.")
}

 


  📍  배열을 전달 받아 짝수만 출력하는 메서드 작업 

fun main() {
   
    val numbers = IntArray(10)
    for (i in numbers.indices) {
        numbers[i] = i + 1
    }
    print("main() : ")
    for (i in numbers.indices) {
        print(numbers[i])
        if (i < numbers.size - 1) {
            print(", ")
        }
    } // main() : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10

    println()
    printOdd(numbers) // printOdd() : 2, 4, 6, 8, 10
}

fun printOdd(numbers: IntArray) {
    print("printOdd() : ")
    for (i in numbers.indices) {
        if (numbers[i] % 2 == 0) {
            print(numbers[i])
            if ( i < numbers.size - 1) {
                print(", ")
            }
        }
    }

    val odds = numbers.filter {result -> result % 2 == 0}
    println(odds)
}

 


  📍 키보드로 부터 학생 수와 각 학생들의 점수를 입력받아서, 최고 점수 및 평균 점수를 구하는 프로그램

fun main() {

    var run = true // 반복문의 조건으로 사용 -> 값이 false가 된다면 반복문이 종료

    var scoreList: IntArray = IntArray(0)
    while (run) {
        println("-----------------------------------------------------")
        println("1.학생수 | 2.점수입력 | 3.점수리스트 | 4.분석 | 5.종료")
        println("-----------------------------------------------------")
        print("선택> ")
        val selectNo: Int = readln().trim().toInt()
        when (selectNo) {
           1 -> scoreList = inputStudentNum() // 학생수를 입력 받아서 배열 생성
           2 -> inputScores(scoreList) // 생성된 배열의 갯수 만큼 점수 입력
           3 -> printScores(scoreList) // 입력받은 배열의 값을 출력
           4 -> printAnalysis(scoreList) // 최고 점수, 평균 점수 출력
           5 -> run = setRun() // run 값 변경
        }
    }
    println("프로그램 종료")
}

fun inputStudentNum():IntArray {
    print("학생수> ")
    var studentNum = readln().toInt()
    return IntArray(studentNum)
}

fun inputScores(scores:IntArray) {
    for (i in scores.indices) {
        print("scores[$i] > ")
        scores[i] = readln().toInt()
    }
}

fun printScores(scores:IntArray) {
    for (i in scores.indices) {
        println("scores[$i] : " + scores[i])
    }
}

fun printAnalysis(scores: IntArray) {
    var max = scores[0]
    var sum = scores[0]
    var avg: Double

    for (i in 1 until scores.size) {
        if (scores[i] > max) {
            max = scores[i]
        }
        sum += scores[i]
    }

    avg = (sum / scores.size).toDouble()
    println("최고 점수: " + max)
    println("평균 점수: " + avg)

}

fun setRun(): Boolean {
    return false
}

 

 

 

[ 내용 참고 : IT 학원 강의 ]


1.  배열  Array

🐝  여러 개의 값을 담을 수 있는 대표적인 자료형인 배열은 값을 담기 전에 먼저 배열 공간의 개수를 할당하거나
      초기화 시에 데이터를 저장해 두면 데이터의 개수만큼 배열을 크기가 결정
🐝  먼저 개수를 정해 놓고 사용해야 하며 중간에 개수를 추가하거나 제거할 수 없음

💡  배열은 다른 데이터 타입과 마찬가지로 변수로 저장해서 사용할 수 있으며 다음과 같은 형태로 선언
      var 변수 = Array(개수)
fun main() {
    // 배열 객체는 Int, Long, Char 등과 같은 기본 타입 뒤에 Array를 붙여서 만듦.
    var students: IntArray = IntArray(10) // 변수 student에 Int(정수형) 공간을 10개 할당하라는 의미
    var longArray = LongArray(10)
    var charArray = CharArray(10)
    var floatArray = FloatArray(10)
    var doubleArray = DoubleArray(10)

    println(students[0]) // 0 -> 따로 초기화 하지 않으면 0으로 초기화.
}

1) 문자열 배열에 빈 공간 할당하기


🍯  String은 기본 타입이 아니기 때문에 StringArray는 없지만 다음과 같이 사용할 수 있음

var stringArray = Array(10, {item -> "" })


🍯  괄호 안의 첫 번째 숫자인 10만 변경해서 사용하면 그 숫자만큼 빈 문자열로 된 배열 공간을 할당
       ➡️  자바에서는 문자열 배열을 생성하면서 초기화 하지 않으면 null이 초기값이 됨
       ➡️  하지만 코틀린은 기본적으로 Null 사용을 허용하지 않기 때문에 빈 문자열을 이용해서 따로 초기화해야 함


2) 값으로 배열 공간 할당하기


🍯  arrayOf() 함수를 사용해서 String 값을 직접 할당할 수도 있음

fun main() {
    var dayArray: Array<String> = arrayOf("MON", "TUE", "WED", "THU", "FRI", "SAT", "SUM")

    var intArray: IntArray = intArrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    var intArray2: Array<Int> = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
}

3) 배열에 값 입력하기

 

🍯  다음은 배열의 인덱스에 있는 값을 바꾸는 방법을 다른 방식으로 표현한 것

 

💡 이 두 방식은 표현식만 다를 뿐 동일한 코드

    1. 배열을 선언한 변수명 옆에 대괄호([])를 사용하고, 대괄호 안에 값을 저장할 위치의 인덱스 번호를 작성
        그리고 등호(=)를 사용해서 값을 입력
       배열명[인덱스] = 값

    2. set 메서드를 사용할 수 있음. 배열이 제공하는 set()메서드에 인덱스와 값을 파라미터로 넘겨주면 됨
       배열명.set(인덱스, 값)
fun main() {
    students[0] = 90
    students.set(1, 91)
}

 4) 배열에 있는 값 꺼내기


🍯  값을 입력할 때와 같은 방식으로 인덱스로 값을 가져올 수 있음

 

💡 대괄호 안에 인덱스를 입력해서 가져올 수 있으며 값을 꺼내는 배열의 메서드는 get()
     배열명[인덱스]
     배열명.get(인덱스)
fun main() {

    // 배열 students의 일곱번째 값을 seventhValue 변수에 저장
    var seventhValue = students[6]

    // 배열 students의 열번째 값을 tenthValue 변수에 저장
    var tenthValue = students.get(9)

}

 


응용 예제
fun main() {
    /* for문을 이용해서 arr 배열의 합을 구하세요 */
    val arr = intArrayOf(10, 20, 30, 40, 50)
    var sum = 0

    // 작성 위치
    // 1. until 사용
    for (i in 0 until arr.size) {
        sum += arr[i]
    }
    println("arr 배열의 합은 $sum")

    // 2. for in 사용
    sum = 0
    for (item in arr) {
        sum += item
    }
    println("arr 배열의 합은 $sum")

    // 3. indices 사용
    println(arr.indices) // 0..4
    sum = 0
    for (i in arr.indices) {
        sum += arr[i]
    }
    println("sum = $sum")
}

 

 

 

[ 내용 참고 : IT 학원 강의 ]

+ Recent posts