20231207 (목) Kotlin 5주차 강의

2023. 12. 7. 21:03TIL

코틀린 심화단계 강의

 

1.<유용한 기능>

우선 이문단은 상당히 길어질것으로 예상

 

자료형의 변환

일반 자료형

예시코드)

	var num1 = 20  //정수만 표시하는 Int 상태
    var num2 = 30.2  //소수까지 표현된 Double 상태

    var num3 = num2.toInt()    //num2에 해당하는값을 Int로 바꾼다. 예상 결과 30
    var num4 = num1.toDouble()  //num1에 해당하는 값을 Double로 바꾼다. 예상 결과 20.0

    var strNum5 = "10"   //Num5와 6은 String 형태이다.
    var strNum6 = "10.21"

    var num5 = Integer.parseInt(strNum5)  //Num5를 Int로 바꾼다.
    var num6 = strNum6.toDouble()  //Num6를 Double로 바꾼다.

    println("num3: $num3")
    println("num4: $num4")
    println("num5: $num5")
    println("num6: $num6")
num3: 30
num4: 20.0
num5: 10
num6: 10.21

 

객체 자료형

이는 특이하게 서로 상속 된 관계에서만 가능하다.

자식에서 부모는 업캐스팅 / 부모에서 자식은 다운캐스팅이라 하며 서로 비슷한듯 하면서 다르다.

예시코드)

업캐스팅

fun main() {
    println("몇 마리를 생성하시겠습니까?")
    var count = readLine()!!.toInt()  //여기에 적는 숫자는 List의 자료 갯수가 된다.
    var birds = mutableListOf<Bird>()

    for(idx in 0..count-1) {  //List는 0부터 시작하기 때문에 적은 숫자에 -1을 하는모습.
        println("조류의 이름을 입력해주세요")
        var name = readLine()!!   //List에 들어갈 새이름을 추가

        // as Bird는 생략가능
        birds.add(Sparrow(name) as Bird) //이는 이해를 돕기위해 as Bird를 추가함
    }
    println("============조류 생성완료============")
    for(bird in birds) {
        bird.fly()
    }
}
open class Bird(name: String) {
    var name: String
    init {
        this.name = name
    }
    fun fly() {
        println("${name}이름의 조류가 날아요~")
    }
}
class Sparrow(name: String): Bird(name) {  //위에서 입력한 이름이 여기에 추가된다
}

 

 

다운캐스팅

fun main() {
    println("몇 마리를 생성하시겠습니까?")
    var count = readLine()!!.toInt()
    var birds = mutableListOf<Bird>()

    for(idx in 0..count-1) {
        println("조류의 이름을 입력해주세요")
        var name = readLine()!!

        birds.add(Sparrow(name) as Bird)
    }
    println("============조류 생성완료============")
    for(bird in birds) {
        bird.fly()
    }
    // 다운캐스팅 오류
    // Sparrow는 Bird가 가져야할 정보를 모두 가지고 있지 않기 때문임
//    var s1:Sparrow = birds.get(0)  위와 완전히 똑같지만 이부분만 다름
}

open class Bird(name: String) {
    var name: String

    init {
        this.name = name
    }

    fun fly() {
        println("${name}이름의 조류가 날아요~")
    }
}

class Sparrow(name: String): Bird(name) {

}

 

다운캐스팅은 이렇듯 자식클래스가 부모클래스의 내용을 모두 갖고있지않아서 변환하기가 힘들다.

 

코틀린은 is 키워드를 활용해서 자료형의 타입을 확인가능하다

	if(name is String) {  //name is String 명령어로 String인지 아닌지 확인
        println("name은 String 타입입니다")
    } else {
        println("name은 String 타입이 아닙니다")
    }

 

또 복수의 데이터를 리턴할수가 있는데

두개이상의 데이터를 포함하는 데이터클래스를 설계하고 리턴하면 된다.

두개에는 Pair 세개에는 Triple을 쓸 수 있다.

fun main() {
    var chicken = Chicken()
    var eggs = chicken.getThreeEggs()
    var listEggs = eggs.toList()
    
//    first, second, third로 관리
//    var firstEgg = eggs.first
//    var secondEgg = eggs.second
//    var eggTime = eggs.third  이는 list를 표시하는 방법중 하나
    
    // 리스트로 관리
    var firstEgg = listEggs[0]
    var secondEgg = listEggs[1]
    var eggTime = listEggs[2]

    println("달걀의 정보는 ${eggs} 입니다.")  //eggs에 대항하는 값을 가져오기때문에 ()형식으로 나온다.
    println("리스트 달걀의 정보는 ${listEggs} 입니다.")  //list를 불러오기때문에 [] 형식으로 나온다
    println("첫번째 달걀의 종류는 ${firstEgg} 입니다.")
    println("두번째 달걀의 종류는 ${secondEgg} 입니다.")
    println("달걀은 ${eggTime}에 나왔습니다.")  //Pair로는 불러올수없는 내용
}

class Chicken {
    fun getTwoEggs(): Pair<String, String> {  //Pair를 적용함. 여기부터
        var eggs = Pair("달걀", "맥반석")
        return eggs
    }                                        //여기까진 없어도 되지만 Pair에 대한 설명때문에 남겨둠

    fun getThreeEggs(): Triple<String, String, Int> { //Triple을 적용함
        var eggs = Triple("달걀", "맥반석", 20230101)  //3번째로 20230101을 추가해준 모습
        return eggs
    }
}

클래스를 여러개로 구분해도 되지만, 매번 그렇게 설계하면 비효율적이다.

 


이후에도 5주차 강의목록이 많이 남아있지만

일단은 계산기 만들기에 몰두하였다.

그렇게 하여서 만든 계산기

 

lv1 조건문을 써서 만든 간단한 계산기

fun main() {
    println("첫번째 숫자를 입력하시오")
    var num1 = readln().toDouble()
    println("사용할 기호를 입력하시오 예) +, -, *, /")
    var op = readln()
    println("두번째 숫자를 입력하시오")
    var num2 = readln().toDouble()

    var calc = Calculator(num1 , op, num2)
    calc.operation()
}
class Calculator(num1: Double, op:String, num2: Double) {
    var num1:Double = num1
    var op:String = op
    var num2:Double = num2
    init {
    }
    fun operation() {
        println("계산 진행 중!")
        if (op == "+") {
            println("${num1} ${op} ${num2} = ${num1+num2}")
        }
        else if(op == "-" ) {
            println("${num1} ${op} ${num2} = ${num1-num2}")
        }
        else if(op == "*" ) {
            println("${num1} ${op} ${num2} = ${num1*num2}")
        }
        else if(op == "/" ){
            println("${num1} ${op} ${num2} = ${num1/num2}")
   

 

lv2 클래스를 활용하기 시작한 단계

fun main() {
    println("첫번째 숫자를 입력하시오")
    var num1 = readln().toDouble()
    println("사용할 기호를 입력하시오 예) +, -, *, /")
    var op = readln()
    println("두번째 숫자를 입력하시오")
    var num2 = readln().toDouble()

    var calc = Calculator2ver2 (num1 , op, num2)
    calc.operation()
}

class Calculator2ver2 (num1: Double, op:String, num2: Double) {
    var num1 = num1
    var op = op
    var num2 = num2
    init {
    }
    fun operation() {
        println("계산 진행 중!")
        when(op) {
            "+" -> {
                println("${num1} ${op} ${num2} = ${num1+num2}")
            }
            "-" -> {
                println("${num1} ${op} ${num2} = ${num1-num2}")
            }
            "*" -> {
                println("${num1} ${op} ${num2} = ${num1*num2}")
            }
            "/" -> {
                println("${num1} ${op} ${num2} = ${num1/num2}")
            }
            "%" -> {
                println("${num1} ${op} ${num2} = ${num1%num2}")
            }
        }
    }
}

 

lv3 클래스를 여러개 만들어서 서로간의 관계를 구축한 단계

fun main() {
    // 처음에 숫자 2개와 사칙연산 기호 입력
    println("첫번째 숫자를 입력해주세요")
    var num1 = readln().toDouble()
    println("사용할 기호를 입력해주세요 예) +, -, *, /")
    var op = readln()
    println("두번째 숫자를 입력해주세요")
    var num2 = readln().toDouble()

    var c = Calc3() // a는 Calc3 클래스를 명시함
    // +, -, *, / 중 어떤 기호를 입력했는지에 따라 어느 메소드를 사용할것인지 나눔
    while (true){
        if (op == "+") { //만약 op가 +라면 ~~
            println("${num1} 더하기 ${num2} 결과는 ${c.add(num1, num2)}입니다.")
            break
        }
        if (op == "-") { //만약 op가 +라면 ~~
            println("${num1} 빼기 ${num2} 결과는 ${c.sub(num1, num2)}입니다.")
            break
        }
        if (op == "*") { //만약 op가 +라면 ~~
            println("${num1} 곱하기 ${num2} 결과는 ${c.mul(num1, num2)}입니다.")
            break
        }
        if (op == "/") { //만약 op가 +라면 ~~
            println("${num1} 나누기 ${num2} 결과는 ${c.div(num1, num2)}입니다.")
            break
        }
        else {
            println("기호를 다시 입력해주세요")
            op = readln()
            continue
        }
    }
}
class Calc3{
    fun add(num1:Double,num2:Double): Double {
        var a = AddOp2()
        return a.operate(num1,num2)
    }
    fun sub(num1:Double,num2:Double): Double {
        var s = SubOp2()
        return s.operate(num1,num2)
    }
    fun mul(num1:Double,num2:Double): Double {
        var m = MulOp2()
        return m.operate(num1,num2)
    }
    fun div(num1:Double,num2:Double): Double {
        var d = DivOp2()
        return d.operate(num1,num2)
    }
}
class AddOp2 {
    fun operate(num1: Double, num2: Double): Double = (num1 + num2).toDouble()
}
class SubOp2 {
    fun operate(num1: Double, num2: Double): Double = (num1 - num2).toDouble()
}
class MulOp2 {
    fun operate(num1: Double, num2: Double): Double = (num1 * num2).toDouble()
}
class DivOp2 {
    fun operate(num1: Double, num2: Double): Double = (num1 / num2).toDouble()
}

 

lv4 추상 클래스를 활용하여 하위 클래스들을 하나로 묶고 다형성을 구축한 단계

fun main() {
    // 처음에 숫자 2개와 사칙연산 기호 입력
    println("첫번째 숫자를 입력해주세요")
    var num1 = readln().toDouble()
    println("사용할 기호를 입력해주세요 예) +, -, *, /")
    var op = readln()
    println("두번째 숫자를 입력해주세요")
    var num2 = readln().toDouble()


    var a = Calculator4() // a는 Calculator4 클래스를 명시함
    // +, -, *, / 중 어떤 기호를 입력했는지에 따라 어느 메소드를 사용할것인지 나눔
    while (true){
        if (op == "+") { //만약 op가 +라면 ~~
            a.operateC(AddOperation2(),num1,num2) //Calculator4의 AddOperation2()를 실행하고 num1 num2를 넣어줌)
            break
        }
        if (op == "-") {
            a.operateC(SubstractOperation2(),num1,num2)
            break
        }
        if (op == "*") {
            a.operateC(MultiplyOperation2(),num1,num2)
            break
        }
        if (op == "/") {
            a.operateC(DivideOperation2(),num1,num2)
            break
        }
        else {
            println("기호를 다시 입력해주세요")
            op = readln()
            continue
        }
    }

}
class Calculator4{
    fun operateC(operation: AbstractOperation, num1: Double, num2: Double) {
        //15줄에서 AddOperation2가 실행가능했던 이유가 operateC는 AbstractOperation를 포함하고있기때문
        operation.operate(num1,num2) //윗줄과 아랫줄 모두 오퍼레이션이 들어감
    }
}
abstract class AbstractOperation {  //추상클래스
    abstract fun operate(num1: Double, num2: Double)//아래 AddOperation2 와 공통되는 부분만 메소드에 표시해놓았다.


}
class AddOperation2 : AbstractOperation() {  //AddOperation2는 AbstractOperation를 상속받고있음
    override fun operate(num1: Double, num2: Double) { //내가 기호로 +를 입력했다면 아래의 문구가 출력된다
        println("${num1} 더하기 ${num2} 결과는 ${num1 + num2} 입니다.")
    }
}
class SubstractOperation2 : AbstractOperation() {  //AbstractOperation를 상속받고있음
    override fun operate(num1: Double, num2: Double) { //내가 기호로 -를 입력했다면 아래의 문구가 출력된다
        println("${num1} 빼기 ${num2} 결과는 ${num1 - num2} 입니다.")
    }
}
class MultiplyOperation2 : AbstractOperation() {  //AbstractOperation를 상속받고있음
    override fun operate(num1: Double, num2: Double) { //내가 기호로 *를 입력했다면 아래의 문구가 출력된다
        println("${num1} 곱하기 ${num2} 결과는 ${num1 * num2} 입니다.")
    }
}
class DivideOperation2 : AbstractOperation() {  //AbstractOperation를 상속받고있음
    override fun operate(num1: Double, num2: Double) { //내가 기호로 /를 입력했다면 아래의 문구가 출력된다
        println("${num1} 나누기 ${num2} 결과는 ${num1 / num2} 입니다.")
    }
}

 

일단 기록으로 남겨둔다.

 

오늘의 한마디 : 내일은 호텔 예약 프로그램좀 만져보도록 하자