카테고리 없음
[Kotlin 27강] Generic
연나연
2024. 1. 8. 10:19

Generic
클래스를 설계할 때 변수의 타입을 유동적으로 하고 싶을 때가 있을 수도 있다.
이 때 Generic 개념을 활용하면 클래스 작성시가 아닌 객체 생성시에 변수의 타입을 설정할 수 있다.
// Generic : 클래스를 작성할 때 프로퍼티, 매개변수 등에 설정되는 자료형을 객체를 생성할 때 // 결정할 수 있도록 하는 개념 fun main(){ // 제네릭 타입은 객체를 생성할 때 타입을 결정해줘야 한다. // T 타입으로 정의된 변수의 타입이 Int 로 결정된다. val t1 = TestClass1<Int>() t1.testMethod1(100) println() val t2 = TestClass1<String>() t2.testMethod1("안녕하슈") println("---------------------------") val t3 = TestClass2<Int, Double, Boolean, String>(100,11.11) t3.testMethod3(true,"문자열1") println("---------------------------") val t4 = TestClass2<Double, String, Boolean, Int>(22.22, "문자열2") t4.testMethod3(false, 200) } // < > : 안에 알바벳 문자를 넣어준다. 보통 대문자 한글자를 작성한다. // 이 알파벳은 아직 결정되지 않은 타입을 의미한다. // 어떠한 타입인지 결정되지 않았지만 이 타입의 변수들을 정의하여 클래스를 작성하고 // 향후, 객체를 생성할 때 타입을 결정할 수 있다. class TestClass1<T>{ fun testMethod1(a1:T){ println("a1 : $a1") } } class TestClass2<A, B, C, D>(var a1:A, var a2:B){ fun testMethod3(a3:C, a4:D){ println("a1 : $a1") println("a2 : $a2") println("a3 : $a3") println("a4 : $a4") } } open class SuperClass1 open class SubClass1() : SuperClass1() class Subclass2 : SubClass1() // 불변성 class TestClass3<T>
가변성
불변성 : 제네릭이 설정된 객체의 주소 값을 같은 타입의 제네릭이 설정된 변수에만 담을 수 있다.
공변성 : 제네릭이 설정된 객체의 주소 값을 부모 클래스 타입의 제네릭이 설정된 변수에도 담을 수 있다(out)
반 공변성 : 제네릭이 설정된 객체의 주소 값을 자식 클래스 타입의 제네릭이 설정된 변수에도 담을 수 있다(in)
이 부분은 좀 복잡하고 크게 쓸 일 없으니, 그냥 이런게 있다! + 개념정도만 알아두자
fun main(){ // 불변성 : 객체를 생성할 때 설정한 제네릭과 같은 변수에 담을 수 있다. // 클래스간의 상속 관계에 상관없이 제네릭에 설정한 클래스 타입이 다르면 오류가 발생한다. val t5:TestClass3<SubClass1> = TestClass3<SubClass1>() //val t6:TestClass3<SuperClass1> = TestClass3<SubClass1>() //val t7:TestClass3<Subclass2> = TestClass3<SubClass1>() // 공변성 : 변수에 설정한 제네릭이 객체를 생성했을 때 사용한 제네릭과 같거나 부모 클래스인 경우에 // 담을 수 있다. val t8:TestClass4<SubClass1> = TestClass4<SubClass1>() val t9:TestClass4<SuperClass1> = TestClass4<SubClass1>() // val t10:TestClass4<SubClass2> = TestClass4<SubClass1>() // 반 공변성 : 변수에 설정한 제네릭이 객체를 생성했을 때 사용한 제네릭과 같거나 자식 클래스인 경우에 // 담을 수 있다. val t11:TestClass5<SubClass1> = TestClass5<SubClass1>() // val t12:TestClass5<SuperClass1> = TestClass5<SubClass1>() val t13:TestClass5<SubClass2> = TestClass5<SubClass1>() } // 불변성 (제네릭에 키워드를 붙히지 않는다) class TestClass3<T> // 공변성 class TestClass4<out A>() // 반공변성 class TestClass5<in A>()