Powerful Functional and OOP in Kotlin
저번 시간까지는 코틀린의 클래스의 기본적인 내용과 인터페이스에 대해서 알아보았습니다. 이번 시간에는 코틀린에서 사용하는 접근 한정자에 대해서 설명을 해볼까 합니다. 접근 한정자란, 프로그램 내부에서 사용되는 변수 및 함수 그리고 클래스의 사용을 제한하거나 자유롭게 하는 데 사용되는 키워드입니다. 몇몇 객체 지향 프로그래밍 언어와 동일하게 클래스의 위치와 같이 선언되거나 변수와 함께 선언되어 컴파일러에게 전달됩니다.
사용법을 알기 전에 왜 그렇다면 접근 한정자를 사용할까요? 만약 아래와 같은 클래스가 있다고 가정해봅니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Foo{
var i:Int = 0;
var j:Int = 10;
fun changeVal(){
val z:Int = i;
i = j;
j = z;
}
fun show(){
println("i : ${i} j : ${j}");
}
}
fun main(){
var foo = Foo()
foo.show()
foo.changeVal()
foo.i = 20 foo.show()
}
|
cs |
값을 변경하는 함수인 changeVal()을 통해서만 Foo클래스 멤버 변수의 값들을 서로 교환(Swap)해주려고 위와 같이 선언했습니다. 하지만 아래 main영역에서 foo의 멤버 변수인 i에 바로 엑세스해서 값을 변경한다면, 의미가 없게 돼버립니다. 예제 코드라서 그렇게 긴장감이란 게 존재하지 않지만, 실 개발에서 위와 같은 코드 작성은 사실 아주 큰 위험을 불러올 확률이 매우 높습니다. "난 그렇게 코드 작성 안 해"라고 말하는 독불장군이라면 어쩔 수 없겠지만, 사람은 실수를 합니다. 기계도 실수를 할 수 있는데, 사람이라고 실수를 안할리 가요.. 그래서 위와 같은 일을 방지하기 위해서, 객체 지향 프로그래밍 패러다임 중 데이터의 은닉이 있습니다. 다른 말로 한다면, "누구누구 이외엔 접근 금지" 이런 의미로 사용됩니다. 그렇다면 이제 사용 예제를 보도록 하겠습니다.
Keyword | Description |
Private | 클래스 내부 메서드나 변수는 모두 좌측의 키워드를 사용해 선언이 가능합니다. private 키워드는 클래스 범위 내에서만 엑세스 할 수 있습니다. 동일한 코드 영역 내에서만 엑세스가 가능합니다. |
Protected | protected를 사용한 클래스 및 인터페이스는 상속받은 인터페이스 혹은 클래스 내에서만 엑세스가 가능합니다. |
Public | 프로젝트 내부 어디에서나 접근이 가능한 한정자입니다. 엑세스 수정자를 지정하지 않으면 컴파일러는 멤버변수를 public의 형태로 변환하게 됩니다. 어디에서나 엑세스가 가능합니다. |
Internal | 코틀린에 새로 추가된 접근 한정자로서, 내부 클래스 등에서만 엑세스가 가능하며, 선언된 패키지 내부에서만 엑세스가 가능하다는 특징이 존재합니다. |
위와 같은 접근 한정자로 구성되어있습니다. 실제로 코드를 작성해보도록 하겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
class PrivateFoo{
private var i:Int = 1;
fun changeVal(){
i += 1;
}
}
open class ProtectedFoo(){
open protected var i = 1;
fun changeVal(){
i += 1;
}
}
class ProtectedFooChild : ProtectedFoo(){
override var i:Int = 10
fun changeVal2() : Int{
i += 1
println(i)
return i
}
}
class InternalFoo{
internal var i:Int = 1;
fun changeVal(){
i+=1;
}
fun show() {println(i);}
}
class PublicFoo{
public var i:Int = 1;
fun changeVal(){
i += 1;
}
fun show() {println(i)}
}
fun main(){
var foo = PrivateFoo()
foo.changeVal()
//foo.i = 10 Error occur : can't access 'i': It is private
var foo1 = ProtectedFoo()
foo1.changeVal()
var foo1child = ProtectedFooChild()
foo1child.changeVal2()
//foo1.i = 10 Error occur : can't access 'i' : It is protected
//but derived class can access the ProtectedFoo
var foo2 = InternalFoo()
foo2.changeVal()
foo2.i = 10 //It can compile
foo2.show()
var foo3 = PublicFoo()
foo3.changeVal()
foo3.i = 10
foo3.show()
}
|
cs |
위와 같이 코드를 작성해보았는데, 코드의 양이 적지 않아 복잡하게 보이지만 뭐 별거 없습니다. 실습을 하시면서 따라오시면 될 것 같습니다.
- private로 선언된 멤버 변수 같은 경우 access되지 않으며 클래스 내부에서만 접근이 가능
- protected로 선언된 멤버 변수 또한 access되지 않지만, 상속받은 클래스에서는 접근이 가능
- internal클래스는 접근은 가능하나 선언 된 패키지 내부에서만 접근이 가능하다는 점 유의
- public으로 선언된 멤버 변수는 언제 어디서든 access가 가능함
정도로 정리해볼 수 있을 것 같습니다!! 이정도면 충분히 사용하는데 무리 없이 이해할 수 있는 선이라고 생각합니다 ㅎㅎㅎㅎ
Method Extension
코틀린의 함수 확장 기능에 대해서 알아보도록 하겠습니다. 저희가 만약 다른 곳에서 선언된 함수를 수정해서 사용하기 위해서는 상속을 통해서 수정을 하는 게 일반적이란 점은 이때까지 잘 따라오신 분이라면 알 수 있으실 듯합니다. 하지만, 여기서는 '.'을 통해서 접근해 수정하고 호출이 가능한 함수를 재생성할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class Foo{
var myVar : String = "Nil"
fun show(){
println(myVar)
}
}
fun main(){
var foo = Foo()
foo.myVar = "Number 1"
foo.show()
var foo2 = Foo()
foo2.myVar = "Number 2"
foo2.show()
var foo3 = Foo()
foo3.myVar = foo.ShowExtension(foo2)
//foo object + foo2 object
foo3.show()
}
fun Foo.ShowExtension(f:Foo):String{
var foo4 = Foo()
foo4.myVar = this.myVar + " " + f.myVar
return foo4.myVar
}
|
cs |
코드를 보게되면 알 수 있듯이, 기본 클래스 외부에서 함수를 정의했습니다. 코틀린에서는 이와 같은 외부에 멤버 함수를 선언하는 것 또한 가능합니다. c++도 이러한 방식으로 함수를 정의하죠? 그러한 방식으로 foo3의 myVar에 함수의 결괏값을 대입해주었습니다
1
2
3
4
5
6
7
8
9
10
11
12
|
fun main(){
println("Hello " + Foo.show())
}
class Foo{
companion object{
fun show():String{
return "World"
}
}
}
|
cs |
코틀린에서는 companion이라는 키워드가 있는데, 이 키워드의 메커니즘은 메서드 내부에 클래스에 대한 객체를 생성할 수 있으며, 클래스의 이름을 참조해 해당 메서드를 호출하는 방식입니다. 정적 객체로 할당하는 것과 동일하게 보일 수 있지만, 실시간으로 컴파일러는 클래스의 함수에 access 할 때 멤버 변수로 객체를 생성하게 됩니다. 확장 속성에도 포함되어 있으며 객체 확장 중 일부 기술입니다!!
오늘까지 코틀린의 접근 한정자와 객체 확장에 대해서 알아보았는데, 사실 그렇게 쉬운 언어는 아닙니다. 사이즈가 어느정도 있는 언어이면서 동시에 객체지향과 함수형의 패러다임을 어느 정도 이해하시면 더욱 이해가 쉽습니다. 그렇다고 그러한 포인트가 없어서 못한다는 건 아니고요, 있으면 도움이 된다는 거죠
글 잘 읽으셨다면, 공감하트 눌러주시면 감사하겠습니다😃
댓글로 피드백, 문의, 질문 모두 받으니까요 편하게 해 주세요!!
감사합니다!🥰🥰🥰🥰🥰🥰🥰
다음 강좌!! ----->
'Kotlin' 카테고리의 다른 글
[Kotlin#8] Kotlin(코틀린) Generics 및 Delegation Pattern In Class[1] (0) | 2020.12.24 |
---|---|
[Kotlin#7] Kotlin(코틀린) 데이터 클래스 및 봉인 클래스(Data Class & Sealed Class) (0) | 2020.12.23 |
[Kotlin#5] Kotlin(코틀린) 클래스 상속 및 인터페이스(Inheritance & Interface) (0) | 2020.12.20 |
[Kotlin#4] Kotlin(코틀린) 클래스 및 객체(class & object) (0) | 2020.12.13 |
[Kotlin#3] Kotlin(코틀린) 제어 및 반복문(if, for, while) (0) | 2020.12.11 |
댓글