[TECHIT] 코틀린 2

hegleB·2023년 5월 24일
post-thumbnail

코틀린 또한 자바와 마찬가지로 객체를 생성하기 위해서는 클래스를 이용한다.

[Kotlin]

fun main() {
    // 클래스를 이용해 객체를 생성한다.
    val obj1:TestClass1 = TestClass1()
    println("obj1 : $obj1")
}

// 클래스를 정의한다.
class TestClass1{

}

[Java]

public final class MainKt {
   public static final void main() {
      TestClass1 obj1 = new TestClass1();
      String var1 = "obj1 : " + obj1;
      System.out.println(var1);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}

public final class TestClass1 {
}

public static final로 선언 되어 있어 매개변수를 갖지 못하고, TestClass1을 보면 public final로 선언되어 있다. 이것으로 볼 때 상속이 될 수 없음을 의미한다.

  
    val obj2 = TestClass1()
    println("obj2 : $obj2")

참조 변수로 선언 시 클래스 타입을 생략이 가능하다

fun main() {
	val obj4 = TestClass2()
    println("obj4 : $obj4")
}
 
class TestClass2

클래스 내부에 내용이 없다면 { }는 생략 가능

[Kotlin]

fun main() {
    val t1 = TestClass1()
    println("t1 : $t1")

    val t2 = TestClass2()
    val t3 = TestClass2(100, 200)

    println("t2.v1 : ${t2.v1}, t2.v2 : ${t2.v2}")
    println("t3.v1 : ${t3.v1}, v3.v2 : ${t3.v2}")
}

class TestClass1{
    // init 코드 블럭
    // 클래스를 통해 객체가 생성되면 자동으로 동작하는 코드를 작성할 수 있다.
    // 매개 변수를 정의할 수 없기 때문에 생성자는 아니다.
    init{
        println("TestClass1의 init 코드 블럭")
        println("객체가 생성되는 자동으로 동작하는 부분입니다")
    }
}

class TestClass2{
    var v1 = 0
    var v2 = 0

    // init 블럭의 코드는 Java파일로 변환될 때
    // 모든 생성자의 가장 위에 코드가 삽입된다.
    // 따라서 init 블럭의 코드가 먼저 수행되고
    // 선택된 생성자가 수행된다.
    init{
        println("init 코드 블럭 입니다")
    }

    // 매개변수가 없는 생성자
    constructor(){
        println("매개 변수가 없는 생성자")
    }

    constructor(v1:Int, v2:Int){
        println("매개 변수가 두 개인 생성자")
        this.v1 = v1
        this.v2 = v2
    }
}

[Java]

public final class MainKt {
   public static final void main() {
      TestClass1 t1 = new TestClass1();
      String var1 = "t1 : " + t1;
      System.out.println(var1);
      TestClass2 t2 = new TestClass2();
      TestClass2 t3 = new TestClass2(100, 200);
      String var3 = "t2.v1 : " + t2.getV1() + ", t2.v2 : " + t2.getV2();
      System.out.println(var3);
      var3 = "t3.v1 : " + t3.getV1() + ", v3.v2 : " + t3.getV2();
      System.out.println(var3);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}

public final class TestClass1 {
   public TestClass1() {
      String var1 = "TestClass1의 init 코드 블럭";
      System.out.println(var1);
      var1 = "객체가 생성되는 자동으로 동작하는 부분입니다";
      System.out.println(var1);
   }
}

public final class TestClass2 {
   private int v1;
   private int v2;

   public final int getV1() {
      return this.v1;
   }

   public final void setV1(int var1) {
      this.v1 = var1;
   }

   public final int getV2() {
      return this.v2;
   }

   public final void setV2(int var1) {
      this.v2 = var1;
   }

   public TestClass2() {
      String var1 = "init 코드 블럭 입니다";
      System.out.println(var1);
      var1 = "매개 변수가 없는 생성자";
      System.out.println(var1);
   }

   public TestClass2(int v1, int v2) {
      String var3 = "init 코드 블럭 입니다";
      System.out.println(var3);
      var3 = "매개 변수가 두 개인 생성자";
      System.out.println(var3);
      this.v1 = v1;
      this.v2 = v2;
   }
}

코틀린에서 init는 객체를 초기화할 때 사용하며 생성자는 아니다. 자바코드를 보면 제일 위쪽에 코드가 삽입되는 것으로 볼 때 init 블록 코드가 먼저 실행된다는 것 을 알 수 있다.
코틀린은 constructor통해 생성자를 생성하고 매개변수가 있어도 되고 없어도 된다. 그리고 constructor의 매개변수가 다르다. 이것으로 볼 때 overloading이 된다는 사실을 알 수 있다.

[Kotlin]

fun main() {
	 val t4 = TestClass3(100, 200)
    println("t4.a1 : ${t4.a1}")
    println("t4.a2 : ${t4.a2}")

    var t5 = TestClass4(1, 1)
    t5.testMethod4()

    var t6 = TestClass4()
    t6.testMethod4()

    var t7 = TestClass4(1)
    t7.testMethod4()
}

class TestClass3 (var a1:Int, var a2:Int)

class TestClass4 (var a1:Int, var a2:Int ){
    var a3 = 0

    init{
        println("init 블럭 코드 입니다.")
    }
    // 추가적인 생성자를 정의할 때는
    // 클래스 이름 옆에 정의한 생성자를 반드시 호출해야 한다.
    constructor() : this(100, 200)

    constructor(a1:Int) : this(a1, 200){
        println("매개 변수가 있는 생성자 호출")
    }

    fun testMethod4(){
        println("a1 : $a1")
        println("a2 : $a2")
        println("a3 : $a3")
    }
}

[Java]

public final class MainKt {
   public static final void main() {
      TestClass3 t4 = new TestClass3(100, 200);
      String var1 = "t4.a1 : " + t4.getA1();
      System.out.println(var1);
      var1 = "t4.a2 : " + t4.getA2();
      System.out.println(var1);
      TestClass4 t5 = new TestClass4(1, 1);
      t5.testMethod4();
      TestClass4 t6 = new TestClass4();
      t6.testMethod4();
      TestClass4 t7 = new TestClass4(1);
      t7.testMethod4();
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }
}

public final class TestClass3 {
   private int a1;
   private int a2;

   public final int getA1() {
      return this.a1;
   }

   public final void setA1(int var1) {
      this.a1 = var1;
   }

   public final int getA2() {
      return this.a2;
   }

   public final void setA2(int var1) {
      this.a2 = var1;
   }

   public TestClass3(int a1, int a2) {
      this.a1 = a1;
      this.a2 = a2;
   }
}

public final class TestClass4 {
   private int a3;
   private int a1;
   private int a2;

   public final int getA3() {
      return this.a3;
   }

   public final void setA3(int var1) {
      this.a3 = var1;
   }

   public final void testMethod4() {
      String var1 = "a1 : " + this.a1;
      System.out.println(var1);
      var1 = "a2 : " + this.a2;
      System.out.println(var1);
      var1 = "a3 : " + this.a3;
      System.out.println(var1);
   }

   public final int getA1() {
      return this.a1;
   }

   public final void setA1(int var1) {
      this.a1 = var1;
   }

   public final int getA2() {
      return this.a2;
   }

   public final void setA2(int var1) {
      this.a2 = var1;
   }

   public TestClass4(int a1, int a2) {
      this.a1 = a1;
      this.a2 = a2;
      String var3 = "init 블럭 코드 입니다.";
      System.out.println(var3);
   }

   public TestClass4() {
      this(100, 200);
   }

   public TestClass4(int a1) {
      this(a1, 200);
      String var2 = "매개 변수가 있는 생성자 호출";
      System.out.println(var2);
   }
}

코틀린은 constructor가 생략이 가능하고 class 클래스명(매개변수1, 매개변수2) 형태로 사용할 수 있다.
이때 클래스 이름 옆에 정의한 생성자를 반드시 호출해야한다.

배운 내용을 활용하여 3문제를 풀었다

문제 1

자판기를 구현한다.
음료수를 고르세요
1. 콜라(1000원), 2. 사이다(1000원), 3.커피(1500원), 4.복숭아아이스트(2000원) : 1
만약 그외의 번호를 입력하면.... 다시 입력해주세요 라고 출력하고 위의 메뉴가 다시 나오게 한다.
현재 0원/부족 1000원
동전을 넣어주세요 : 500
현재 500원/부족 500원
동전을 넣어주세요 : 1000
현재 1500원/부족 0원
콜라가 나왔습니다.
잔액은 500원 입니다.
콜라는 1000원이고
양은 300ml 입니다
회사는 코카콜라 입니다.
사이다는 1000원이고
양은 300ml 입니다
회사는 칠성입니다.
커피는 1500원이고
양은 500ml 입니다
회사는 별다방입니다.
복숭아아스티는 2000원이고
양은 700ml 입니다
회사는 빽다방입니다

// 자판기 클래스
class VendingMachine{
    val scanner = Scanner(System.`in`)
    // 음료수 번호를 입력받는 기능
    fun inputItemNumber() : Int{
        var choiceNumber = 0

        do{
            println("음료수를 고르세요")
            print("1. 콜라(1000원), 2. 사이다(1000원), 3.커피(1500원), 4.복숭아아이스트(2000원) : ")
            choiceNumber = scanner.nextInt()
            // 입력한 번호가 1 ~ 4가 아니라면 ..
            if(choiceNumber !in 1..4){
                println("다시 입력해주세요")
            }
        } while(choiceNumber !in 1..4)

        return choiceNumber
    }
    // 동전 입력 기능
    fun insertCoin(vendingItem: VendingItem) : Int{
        // 입력한 동전
        var coin = 0

        while(coin < vendingItem.price){
            println("현재 : ${coin}원 / 부족 : ${vendingItem.price - coin}원")
            print("동전을 넣어주세요 : ")
            val inputCoin = scanner.nextInt()
            coin += inputCoin
        }
        println("현재 : ${coin}원 / 부족 : 0원")

        return coin
    }
    // 음료수가 나오는 기능
    fun exitItem(vendingItem: VendingItem, coinCount:Int){
        // 입력한 동전에서 상품가격을 빼준다.
        val overCoinCount = coinCount - vendingItem.price

        println("${vendingItem.name}이(가) 나왔습니다")
        println("잔액은 ${overCoinCount}원 입니다")

        vendingItem.printItemInfo()
    }

    // 번호에 따라 음료수 객체를 생성하여 반환하는 함수
    fun getItem(itemNumber:Int) = when(itemNumber){
        1 -> VendingItem("콜라", 1000, 300, "코카콜라")
        2 -> VendingItem("사이다", 1000, 300, "칠성")
        3 -> VendingItem("커피", 1500, 500, "별다방")
        4 -> VendingItem("복숭아아이스티", 2000, 700, "빽다방")
        else -> VendingItem("아무거나", 3000, 100, "아무거나")
    }
}
// 음료수 클래스
class VendingItem (var name:String, var price:Int, var volume:Int, var company:String){

    // 음료수 정보를 출력하는 함수
    fun printItemInfo(){
        println("${name}은(는) ${price}이고")
        println("양은 ${volume}ml 입니다")
        println("회사는 ${company}입니다")
    }
}

[설계]
자판기 클래스 : 음료수 선택하는 메서드, 동전 입력 메서드, 음료수 나오는 메서드, 음료수 객체 반환하는 메서드
음료수 클래스 : 음료수 정보 출력 메서드

문제 2

문제 2번은 자판기문제를 변형하여 만든 것으로 자판기 대신 장난감을 생성하는 공장에서 생성할 장난감을 선택하고 총 개수, 생성된 장난감 개수, 총 가격, 평균 가격을 출력하는 문제이;다.

[내가 작성한 코드]

import java.util.*
import kotlin.collections.ArrayList

fun main() {
    val factory = Factory()

    factory.generateToy()
    factory.printTotalToy()
    factory.printTotal()
}

// 공장 클래스
class Factory {

    val toys = ArrayList<Toy>()
    var total = 0
    var robot = 0
    var lego = 0
    var gun = 0
    var doll = 0

    private fun inputToyItem(): Int {
        val scanner = Scanner(System.`in`)
        var toyItem = 0
        do {
            println(
                """
            생산할 장난감의 종류를 선택해주세요
            1. 로보트 장난감, 2. 레고, 3. BB탄 총, 4. 잠만보인형, 0. 생산끝
        """.trimIndent()
            )
            toyItem = scanner.nextInt()
            if (toyItem !in 0..4) {
                println("잘못 입력하였습니다")
            }
        } while (toyItem !in 0..4)
        calToyCount(toyItem)
        return toyItem
    }

    fun generateToy() {
        while (true) {
            val inputItem = inputToyItem()
            if (inputItem == 0) {
                break
            }
            toys.add(getToy(inputItem))
        }
    }

    private fun calToyCount(toyItem: Int) {
        total += 1
        when (toyItem) {
            1 -> robot += 1
            2 -> lego += 1
            3 -> gun += 1
            4 -> doll += 1
        }
    }

    private fun getToy(inputToyItem: Int): Toy {
        return when (inputToyItem) {
            1 -> Toy("로보트", 5000)
            2 -> Toy("래고", 50000)
            3 -> Toy("BB탄 총", 10000)
            else -> Toy("잠만보 인형", 20000)
        }
    }

    fun printTotalToy() {
        println(
            """
           총 : ${total - 1}개
           로보트 장난감 : ${robot}개
           레고 : ${lego}개
           BB탄 총 : ${gun}개
           잠만보인형 : ${doll}개
        """.trimIndent()
        )
        println()
    }

    fun printTotal() {
        var toyTotalPrice = 0

        for (toy in toys) {
            toy.printToyInfo()
            toyTotalPrice+=toy.price
        }
        println("생산된 장난감 총 가격 : ${toyTotalPrice}원\n" +
                "생산된 장난감 평균 가격 : ${toyTotalPrice/toys.size}원")
    }
}

// 장난감 클래스
class Toy(var name: String, var price: Int) {
    fun printToyInfo() {
        println(
            """
            $name
            가격 : ${price}원
            크기 : ${name}만큼 크다
        """.trimIndent()
        )
        println()
    }
}

[강사님이 작성한 코드]

import java.util.*
import kotlin.collections.ArrayList

fun main() {
    val toyFactory = ToyFactory()
    // 생산할 장난감 번호를 입력 받는다.
    var selectNumber = 0
    // 0 을 입력할 때 까지 반복한다.
    do {
        selectNumber = toyFactory.selectToyType()
        // print(selectNumber)
        // 장난값을 생산한다.
        if (selectNumber != 0) {
            val toy = toyFactory.createToy(selectNumber)
            // println(toy.name)
            // 장난감을 저장한다.
            toyFactory.addToy(toy)
        }
    } while (selectNumber != 0)

    // 생산이 완료되면 생산된 장난감 개수를 출력한다.
    toyFactory.printToyCount()

    // 장난감들의 정보를 출력한다.
    toyFactory.printToyInfo()

    // 장난감 가격의 총합과 평균을 출력한다.
    toyFactory.printToyTotalAvgPrice()
}

// 장난감 공장 클래스
class ToyFactory {

    val scanner = Scanner(System.`in`)
    val toyList = ArrayList<Toy>()

    // 생산할 장난감의 종류를 선택하는 기능
    fun selectToyType(): Int {
        var selectNumber = 0

        do {
            println("생산할 장난감의 종류를 선택해주세요")
            println("1. 로보트 장난감, 2. 레고, 3. BB탄 총, 4. 잠만보인형, 0. 생산끝")
            print("번호 입력 : ")
            selectNumber = scanner.nextInt()

            if (selectNumber !in 0..4) {
                println("잘못 입력하였습니다")
            }
        } while (selectNumber !in 0..4)

        return selectNumber
    }

    // 생산한 장난감의 수를 구해 출력하는 기능
    fun printToyCount() {
        var robotCount = 0
        var legoCount = 0
        var bbGunCount = 0
        var jammanboCount = 0

        println("총 : ${toyList.size} 개")

        // 각 장난감의 개수를 계산한다.
        for (tempToy in toyList) {
            when (tempToy.name) {
                "로보트 장난감" -> robotCount++
                "레고" -> legoCount++
                "BB탄 총" -> bbGunCount++
                "잠만보인형" -> jammanboCount++
            }
        }

        //        for(tempToy in toyList){
//            if(tempToy.name == "로보트 장난감"){
//                robotCount++
//            } else if(tempToy.name == "레고"){
//                legoCount++
//            } else if(tempToy.name == "BB탄 총"){
//                bbGunCount++
//            } else if(tempToy.name == "잠만보인형"){
//                jammanboCount++
//            }
//        }

        println("로보트 장난감 : $robotCount 개")
        println("레고 : $legoCount 개")
        println("BB탄 총 : $bbGunCount 개")
        println("잠만보인형 : $jammanboCount 개")
    }

    // 생산한 장난감들의 정보를 출력하는 기능
    fun printToyInfo(){
        // 장난감의 수 만큼 반복한다.
        for(tempToy in toyList){
            tempToy.printToyInfo()
        }
    }

    // 생산한 장난감들의 총 가격과 평균 가격을 구해 출력하는 기능
    fun printToyTotalAvgPrice() {
        // 장난감들의 가격의 총합을 담을 변수
        var priceTotal = 0
        // 장난감의 수 만큼 반복한다.
        for(tempToy in toyList){
            priceTotal += tempToy.price
        }
        // 평균을 구한다.
        val priceAvg = priceTotal / toyList.size

        println("생산된 장난감 총 가격 : ${priceTotal}원")
        println("생산된 장난감 평균 가격 : ${priceAvg}원")
    }

    // 장난감을 생산하여 반환하는 메서드
    fun createToy(toyType: Int) = when (toyType) {
        1 -> Toy("로보트 장난감", 5000, "로보트만큼 크다")
        2 -> Toy("레고", 50000, "레고만큼 크다")
        3 -> Toy("BB탄 총", 10000, "BB탄 총 만큼 크다")
        4 -> Toy("잠만보인형", 20000, "잠만보 만큼 크다")
        else -> Toy("아무장난감", 0, "아무장난감")
    }

    // 생산된 장난감을 저장한다.
    fun addToy(toy: Toy) {
        toyList.add(toy)
    }
}

// 장난감 클래스
class Toy(var name: String, var price: Int, var size: String) {

    fun printToyInfo() {
        println(name)
        println("가격 : $price")
        println("크기 : $size")
    }
}

크게 다른점은 없지만 createToy메서드에서 반환 타입을 생략한 점 그리고 RawString을 사용했다는 점 외에는 크게 다르지 않는 것 같다.

문제3

문제3번은 문제2번과 크게 다르지 않아 따로 작성하지는 않았다.

profile
성장하는 개발자

0개의 댓글