Powerful Functional and OOP in Kotlin
저번 시간에는 코틀린의 클래스 내부에서 선언되는 접근 한정자에 대해서 알아보았습니다. 이번 시간에는 코틀린에서의 데이터 클래스와 봉인 클래스(Sealed Class)에 대해서 알아보도록 하겠습니다. 우선 클래스가 만약 data로 선언되면 해당 클래스는 프로그램 내부에서 데이터 클래스로 표시될 수 있습니다. 이러한 데이터 클래스는 어떻게 보면 데이터만 담은 struct구조와도 유사하며, 파이썬의 nametuple과도 비슷하다고 느껴집니다. 물론 저의 개인적인 생각이기는 하나, 꽤나 유사한 부분이 존재합니다. 데이터 클래스는 기본 생성자로부터 시작하며, 동시에 데이터의 클래스이기 때문에 최소한 하나의 매개변수가 필요합니다.
데이터 클래스는 데이터의 클래스의 빌트인 함수를 사용해서 객체의 연산을 수행하는 것 또한 지원합니다. 그리고 데이터 클래스는 abstract, open, internal 등 과 같은 수정자와 함께 사용될 순 없다는 점이 존재합니다. 그렇다면 제가 생각하는 C와 Python, 그리고 코틀린의 코드를 모두 보고 비교를 진행해보도록 하겠습니다!!
/* Python Code */
1
2
3
4
5
6
7
8
9
10
11
12
|
from collections import namedtuple
class Foo:
def __init__(self, a ):
self.a = a
bar = namedtuple("Bar", ({"a" : 10}))
if __name__ == "__main__":
foo = Foo(11)
print(f'{foo.a} and {bar.a}')
|
cs |
/* C code */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include <stdio.h>
#include <stdlib.h>
typedef struct Foo{
int var;
char *name;
}Foo;
int
main()
{
Foo *foo = malloc(sizeof(Foo));
foo->var = 10;
foo->name = "Gildong";
printf("%s age is %d",foo->name, foo->var);
return 0;
}
|
cs |
/* Kotlin Code */
1
2
3
4
5
6
7
8
|
fun main(){
var Person:Foo = Foo("Gildong", 12);
println("${Person.name} age is ${Person.age}")
}
data class Foo(var name:String, var age:Int)
|
cs |
총 세가지의 언어로 같은 내용의 코드가 작성되었습니다. 하지만 설명하고자 하는 코틀린의 데이터 클래스의 의미를 어쩌면 파이썬이나 C언어에서 얻었을 수 도 있었겠다는 생각이 듭니다. 사실상 문법만 다를 뿐이니 구현하고자 하는 프로그램의 결과는 모두 같습니다. 변수를 담을 수 있는 객체를 반환하는 것인데 다른 뼈대가 존재하는 것이 아닌 데이터의 분리만을 지향한 방식이라고 볼 수 있습니다. 위와 같은 방식은 어떤 프로그래밍 언어나 가지고 있는 기능으로 익숙하시리라 생각하지만, 그럼에도 불구하고 확실하게 알고 가는 것이 좋다고 생각이 듭니다. 모든 코드를 실습해보시는 것을 추천드립니다!!
Sealed Class
제가 앞서 위 클래스를 봉인 클래스라고 했는데, 우리나라 말로 하면 그렇더군요... 뭐 여하튼 알아봅시다. 비슷한 용어가 c#에도 있었던 것 같은데, 사실 c#같은 경우엔 따로 문법을 본 적이 없어서 잘 모르겠네요 다만, 말 그대로 제한된, 봉인된 클래스 레이어를 의미하는 클래스입니다. 또한 Sealed키워드를 이용해서 미리 정의 한 데이터 유형을 컴파일러엑 변경하지 못하게 막는 역할 또한 합니다. 그러니까 만약 자체적으로 하위 클래스(중첩 x)를 가질 수 있으며, 이에 대한 유형 또한 한번 선언된 이후로 아무도 수정을 할 수 없습니다. 게다가, 동일한 코틀린 파일 내부에서만 선언되어야 한다는 점 또한 유의해야 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
sealed class Foo{
class foo: Foo(){
fun fooOfFoo(){
println("fooOfFoo")
}
}
class bar: Foo(){
fun barOfFoo(){
println("barOfFoo")
}
}
}
fun main(array:Array<String>){
val boo:Foo = Foo.foo()
val booOut = when(boo){
is Foo.foo -> boo.fooOfFoo();
is Foo.bar -> "Can't call"
}
println(booOut)
}
|
cs |
위처럼 sealed클래스 또한 여느 클래스와 다를 바 없이 하위 클래스를 가질 수 있습니다. 현재 Foo클래스는 두 개 유형의 클래스를 가집니다. main에서 클래스에 객체를 생성하고 런타임에 할당되기 때문에 이를 동적 바인딩이라고 합니다. 실습을 해보시면서 차근차근 위의 말들을 곱씹으면 이해가 충분히 잘될 것이라고 생각이 듭니다!!
글 잘 읽으셨다면 공감 하트 한 번씩 눌러주시면 감사하겠습니다!😁
댓글로 문의 피드백, 질문 모두 환영하니까요 편하게 달아주세요!!
감사합니다!!😍😍😍😍😍😍😍
다음 강좌 -->
댓글