1.  프로퍼티와 메서드의 재정의 : 오버라이드

👩🏻‍💻  상속받은 부모 클래스의 프로퍼티와 메서드 중에 자식 클래스에서는 다른 용도로 사용해야 하는 경우가 있음
👩🏻‍💻  동일한 이름의 메서드나 프로퍼티를 사용할 필요가 있을 경우에 override 키워드를 사용해서 재정의 할 수 있음
👩🏻‍💻  오버라이드 할 때는 프로퍼티나 메서드도 클래스 처럼 앞에 open을 붙여서 상속할 준비가 되어 있어야 함

 

메서드 오버라이드


    📍 상속할 메서드 앞에 open 키워드를 붙이면 오버라이드 할 수 있지만, open 키워드가 없는 메서드는 오버라이드 할 수 없음

    open class BaseClass {
        open fun opened() {

        }
        fun notOpened() {

        }
    }

    class ChildClass : BaseClass() {
        override fun opened() {
            super.opened()
        }
    }

 

 

프로퍼티 오버라이드


    📍 메서드 오버라이드처럼 프로퍼티 역시 open으로 열려 있어야만 오버라이드를 할 수 있음

    open class BaseClass2 {
        open var opened: String = "I am"
    }
    class ChildClass2: BaseClass2() {
        override var opened: String = "You are"
    }

 


2.  추상 클래스

🚀  추상 클래스는 그 자체로는 객체를 만들 수 없는 클래스로, 일반적으로 추상 메소드가 포함된 클래스를 말함
        ➡️  추상 메소드란 아직 구현되지 않고 추상적으로만 존재하는 메소드
🚀  추상 클래스와 추상 메소드 앞에는 abstract 키워드를 붙임
🚀  상속받는 자식 클래스에 특정 메소드 구현을 강제하고 싶을 때 사용
🚀  추상 클래스 자체로는 직접 객체를 만들 수 없고 자식 클래스에서 추상 메소드를 구현한 다음, 자식 클래스의 객체를 생성하면 됨.

abstract class Game {

    fun startGame() {
        println("게임을 시작했습니다.")
    }
    // 추상 메소드
    abstract fun printName()
}

class OverWatch: Game() {
    override fun printName() { // 추상 메소드 구현
        println("오버워치입니다.")
    }
}

fun main() {
    val overWatch = OverWatch()
    overWatch.startGame() // 게임을 시작했습니다.
    overWatch.printName() // 오버워치입니다.
}

 

 

 

[ 내용 참고 : 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