ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Kotlin] 코틀린 class (open, data , sealed, internal class)
    코틀린 공부/코틀린 기초 2024. 5. 17. 15:04

    자바에는 없는 코틀린 class에서 다른 키워드들을 학습해보려고 한다. (open, data, internal class)

     

    1. open class

    기존에 자바에서는 일반 class를 상속하는 것이 가능했다. 

    class Parent{}
    class Child extends Parent{}

     

    코틀린에서는 class를 상속하기 위해서는 open이라는 키워드를 같이 사용해야 한다. 왜냐하면 코틀린에서는 기본적으로 클래스와 메스드가 다 final 이기 때문이다.

    open class Parent {}
    class Child:Parent() {}

     

    메서드를 상속하고 싶다면 open을 붙여줘야 한다. 

    open class Animal(var name:String, var age: Int) {
        open fun introduce(){
            println("Animal : $name $age ")
        }
    }
    
    class Dog(name:String, age:Int) : Animal(name, age){
        override fun introduce(){
            println("Dog : $name $age ")
        }
    }
    

     

    결론적으로, class와 open class의 차이는 상속불가능 vs 상속 가능의 차이이다. 

     

    2. data class

     

    일반 class에서 다양한 메소드를 자동적으로 생성해줘서 편리하게 사용하게 만들어진 것이 data class다.

     

    같이 생성되는 것들

    • hashCode()
    • copy()
    • equals()
    • toString()
    • componentsN()

    메소드 설명 :

    더보기
    1. hashCode():
      • hashCode() 메서드는 객체의 해시 코드를 반환합니다. 해시 코드는 주로 해시 테이블과 같은 자료 구조에서 객체를 빠르게 찾기 위해 사용됩니다.
      • data class의 hashCode()는 모든 속성의 해시 코드를 기반으로 생성됩니다. 즉, 두 객체의 속성들이 모두 같다면, 이들의 해시 코드도 동일하게 생성됩니다.
    2. copy():
      • copy() 메서드는 객체를 복사하는 메서드로, 선택적으로 일부 속성의 값을 변경할 수 있습니다.
      • 예를 들어, val obj2 = obj1.copy(prop1 = newValue)와 같이 사용하면, obj1을 복사하되 prop1의 값을 newValue로 변경한 새로운 객체를 생성합니다.
      • (코틀린에서는 일반적으로 모든 변수를 val로 선언해 불변으로 놓고 변해야 하는 변수가 있다면 copy를 사용해서 해당 변수만 바꿔서 복사해서 사용한다고 한다. )
    3. equals():
      • equals() 메서드는 두 객체의 내용이 같은지 비교합니다.
      • data class의 equals()는 모든 속성들이 동일한지 비교하여 동일하면 true, 그렇지 않으면 false를 반환합니다. 이를 통해 객체의 속성 값들을 기준으로 동등성을 판단합니다.
    4. toString():
      • toString() 메서드는 객체의 문자열 표현을 반환합니다.
      • data class의 toString()은 클래스 이름과 함께 각 속성의 이름과 값을 포함한 문자열을 반환합니다. 예를 들어, Person(name=John, age=30)과 같은 형태로 출력됩니다.
    5. componentN():
      • componentN() 메서드는 각 속성을 반환하는 메서드로, 여기서 N은 속성의 순서를 나타냅니다.
      • 예를 들어, component1()은 첫 번째 속성을, component2()는 두 번째 속성을 반환합니다.
      • 이러한 메서드는 주로 Destructuring Declarations에서 사용됩니다. 예를 들어, val (name, age) = person과 같이 사용할 수 있습니다. 이는 component1()과 component2() 메서드를 호출하여 각각의 값을 할당합니다.

     

    그리고 Data Class는 아래와 같은 규칙을 갖고 있어 알아둘 필요성이 있다. 

    • 기본 생성자 안에 1개 이상의 파라미터가 있어야 한다.
    • 기본 생성자의 파라미터가 val 또는 var로 선언되어야 한다. 
    • 다른 클래스를 상속받을 수 없다. 단, sealed 클래스는 상속받을 수 있다.
    • abstract, open, sealed, inner와 같은 keyword와 함께 사용할 수 없다. 
    fun main(){
        val p1 = Person(30,"JJJ")
        val p2 = Person(30,"JJJ")
    
        // 내용이 같은지 검사
        println(p1==p2)
    
        // 같은 인스턴스인지 검사 (즉, 메모리 주소가 같은지 검사한다는 것 같음)
        println(p1===p2)
        println(p1.toString())
    
        val p3 = Person2(30, "JJJ")
        println(p3.toString())
    
    }
    
    data class Person(val age: Int, val name: String)
    class Person2(val age: Int, val name: String)
    
    
    // 결과 
    true
    false
    Person(age=30, name=JJJ)
    com.example.kotlinpractice.class_example.data_class.Person2@3d24753a

     

    3. Sealed class

    코틀린에서 sealed class란 다른 클래스가 상속받지 못하도록 제한하는 클래스이다. sealed class의 하위 클래스에서만 상속받을 수 있다. 클래스 계층 구조에서 제한된 개수의 클래스를 나타낼때 사용하게 된다.

    sealed class Vehicle {
        abstract val info:Int
    
        data class Car(val name: String) : Vehicle(){
            override val info: Int
                get() = 1
        }
    
        data class Truck(val name: String) : Vehicle(){
            override val info: Int
                get() = 2
        }
    }

     

    sealed class 특징 :

    • 상속을 제한한다.
      • sealed class는 다른 클래스에서 상속을 받지 못하도록 제한한다. 그래서 sealed class의 내부에 정의해서 사용.
    • 유한한 개수의 하위 클래스를 갖는다. 
      • 상속이 제한되기 때문에 유한한 개수의 하위 클래스를 가진다.
    • 하위 클래스의 종류를 제한한다. 
      • 하위 클래스의 종류를 제한하여 클래스 계층 구조를 제한 할 수 있다. 

     

    sealed class 장점 :

    • 1. 코드 안정성 향상
      • 컴파일 타임때 모든 하위 클래스를 확인하고 사용할 수 있기 때문에 안정성 향상 가능
    • 2. 가독성 향상 
      • 클래스 계층 구조가 명확해 지기 때문에 코드의 가독성이 향상되고 유지보수성이 향상
    • 3. 패턴 매칭
      • 패턴 매칭은 일반적으로 타입이 서로 다른 값들을 패턴으로 지정하고, 해당 값이 각각 어떤 타입인지 판별하는 기능이다.  이런 경우 가독성을 높일수 있다. 
    when (vehicle) {
        is Vehicle.Car -> println("car  :${vehicle.name}.")
        is Vehicle.Truck -> println("truck : ${vehicle.name}.")
    }

     

    만약 sealed class를 안썼다면 else를 추가해야 한다. 

     

    이것보다 더 간단하게 만들어보자면 

    sealed class Vehicle {
        abstract fun print()
        abstract val info:Int
    
        data class Car(val name: String) : Vehicle(){
            override val info: Int
                get() = 1
    
            override fun print() {
                println("This is a Car named ${name}.")
            }
    
        }
    
        data class Truck(val name: String) : Vehicle(){
            override val info: Int
                get() = 2
    
            override fun print() {
                println("This is a dog named ${name}.")
            }
        }
    }

     

    fun printAnimalInfo(vehicle: Vehicle) {
        when (vehicle) {
            is Vehicle.Car -> println("car  :${vehicle.name}.")
            is Vehicle.Truck -> println("truck : ${vehicle.name}.")
        }
    }
    
    fun printAnimalInfo2(vehicle: Vehicle) {
        vehicle.print()
    }

     

    이런식으로도 사용 가능하다.

     

    4. internal class

     

    internal class는 자바에는 없기 때문에 이게 뭔지 혼란스러웠다. 그래서 우선 접근 제한자가 자바와 코틀린에더 어떻게 다른지 알아보자면

     

    자바 :

    • public : 접근을 제한이 없음
    • protected : 동일한 패키지 내에 존재하거나 파생클래스에서만 접근 가능
    • default : 아무런 접근 제한자를 명시하지 않으면 default 값이 되며, 동일한 패키지 내에서만 접근이 가능
    • private : 자기 자신의 클래스 내에서만 접근이 가능

    코틀린 : 

    • Private : 해당 파일이나 클래스에서만 사용을 가능하게 합니다.
    • Public : 어디에서나 접근을 할 수가 있고, 만약 함수나 클래스 앞 아무것도 붙이지 않으면 디폴트로 지정이 되어서 따로 붙일 필요가 없습니다.
    • Protected : 상속받는 인터페이스, 클래스 또는 자식 클래스에서 만 접근이 가능합니다.
    • Internal : 코틀린에서 새롭게 추가된 접근 제한자이고, 같은 프로젝트 모듈 안 에서는 다 접근이 가능 합니다.

     

Designed by Tistory.