Kotlin Programming Intermediate - 8

Beautify.log·2022년 1월 26일
0

Kotlin for Android

목록 보기
8/11
post-thumbnail

Composition


개요

컴포지션은 클래스 안에서 클래스를 사용하는 것을 말합니다.

정확히 말하면 클래스 안에서 다른 클래스를 객체로 생성하여 사용하는 개념입니다.

예시

가령 아래와 같은 클래스가 있다고 가정해봅시다.

class Engine(power:String) {
    fun start() = println("Engine had been started")
    fun stop() = println("Engine has been stopped")
}

멤버변수 power와 멤버 메서드 startstop을 갖습니다.

이렇게 만들어진 클래스를 객체로 생성하여 다른 클래스에서 사용해보겠습니다.

class Car(val name:String, val power:String) {

    private var engine = Engine(power)

    fun startEngine() = engine.start()
    fun stopEngine() = engine.stop()

}

Car라는 클래스 안에서 Engine이라는 클래스로 객체를 생성해주었고 여기에서는 name이라는 멤버변수가 생성자에 포함되어 있습니다.

여기에서 원래 Engine 클래스의 멤버변수로 power라는 변수가 있었기 때문에 Engine 객체의 변수로 받아주기 위해 Car의 생성자에 Engine 객체의 멤버변수를 넣어주었습니다.

클래스 내부에서 클래스를 생성하였기 때문에 멤버 메서드를 호출해서 사용할 수 있습니다.

이 때는 상속 개념이 아니기 때문에 오버라이드라고 말할 수 없습니다.


제네릭


제네릭은 타입을 파라미터로 가지는 클래스와 인터페이스를 의미합니다.

이전에 자료형 변수로 정의하였으며 각 타입 파라미터는 다음과 같았습니다.

E - Element
K - Key
N - Number
T - Type
V - Value
R - ReturnType

클래스에서 제네릭 사용하기

클래스를 선언할 때 제네릭을 사용할 수 있습니다.

예를 들어

class Box<T>(var value:T)

이라는 클래스를 선언한다면 이 클래스를 객체로 생성할 때 T라는 자리에 알맞은 자료형을 넣어주면 됩니다.

이 클래스를 메인함수에서 객체로 만들어 사용한다면

fun main(args: Array<String>) {

	val box:Box<Int> = Box<Int>(123)
	println(box.value)

}

이렇게 Int 타입으로 선언하여 value로 123을 넣어 콘솔에 출력하도록 했습니다.

이처럼 <T>는 불특정 자료형임을 알려주고, 객체로 생성하여 사용할 때 자료형을 밝혀주어 사용할 수 있습니다.

함수에서 제네릭 사용

함수도 마찬가지 입니다.

fun<T> add(x:T, y:T, op:(T, T) -> T) : T = op(x, y)

다음과 같은 함수가 있다고 가정할 때,
T는 어떤 자료형이 올 지 사용되기 전까지는 지정되지 않은 형태입니다.

이 함수는 자료형 T를 갖는 두 개의 매개변수를 받아 이를 처리하여 하나의 자료형으로 return 해주는 형태입니다.

이 때 매개변수의 op는 두개의 자료형에 대해 하나의 자료형으로 처리해주는 메서드입니다.

리턴해줄 값은 op(x, y)의 연산결과입니다.

fun main(args: Array<String>) {

	val res = add(3, 4) {x, y -> x + y}
	println(res)

}

위와 같이 메인함수에서 사용할 수 있습니다. 각각의 매개변수를 받고 op 메서드는 두 값에 대해 덧셈 연산을 해줍니다.

제네릭을 한개만 사용할 수 있는 것은 아닙니다.

class MyClass<T1, T2>(n1:T1, n2:T2) {
    var num1 = n1
    var num2 = n2

    /*
    fun myFunction() {
        return num1 + num2      // 자료형이 명확하지 않으므로 연산할 수 없음
    }
    */

}

주의해야 할 사항으로 제네릭을 갖는 클래스에서는 연산 결과를 리턴하는 멤버 메서드를 생성할 수 없습니다.

자료형이 명확하지 않기 때문에 연산할 수 없는 것입니다.

메인함수에서 다음과 같이 사용하였습니다.

fun main(args: Array<String>) {

    val cal:MyClass<Int, Double> = MyClass<Int, Double>(43, 4995.12)
    println(cal.num1)
    println(cal.num2)

}
profile
tried ? drinkCoffee : keepGoing;

0개의 댓글