728x90

코틀린 강의 시리즈는 이미 자바 문법을 어느정도 안다는 가정하에서 진행을 한다.

따라서 자바 문법을 모르는 상태에서 코틀린의 강의를 들을 수 없으므로 자바부터 배워오길 바란다.

또한 강의의 전반적인 내용은 코틀린에 대한 새로운 문법을 소개하며 자바와 어떻게 다른지를 비교한다.

코틀린은 자바와 같은 jvm족이므로 둘의 협업역시 중요하므로 둘이 어떻게 호환이 되는지도 다루게 된다.

그리고 이 강의는 코틀린 강의지 안드로이드 강의가 아니다. 안드로이드 강의는 알아서하고 코틀린을 적용시키는건 본인 재량이다.


필자는 강의시 원래 IDE에 대한 설명을 최대한 배제하려한다.

필자 블로그의 카테고리는 programming과 usage 둘로 나뉘어 있다.

따라서 프로그래밍은 programming에, IDE및 사용법들은 usage에 나뉘는 방식으로 포스팅을 해왔다.

그런데 코틀린은 조금 상황이 다른게 이미 자바를 알고 있고 자바와 협업한다는 가정하에서 포스팅을 하기에

주변상황에 대한 설명이 들어갈 확률이 매우 높다고 할 수 있다.

따라서 IDE나 사용법에 대한 설명을 같이 포스팅한 경우가 많다. 물론 보는 입장에선 이게 더 도움은 될것이다.

필자가 사용하는 IDE는 IntelliJ가 될것이다. 자바든 코틀린이든 둘다 IntelliJ로 하게 될것이다.


참고:

코틀린 컴파일러 콘솔로 실행하기

코틀린 프로젝트만들기 - InteliiJ

코틀린 프로젝트만들기 - Eclipse


이제 상속을 interface에 대해서 알아보자.

자바에서는 interface의 상속과 class의 상속은 다른 상속의 개념이 였다. 따라서 지시자조차 달랐다.

코틀린에서는 둘의 지시자가 통일되었다. 그러나 interface를 쓰는 방법이 매우 달라졌다.

자바같은 느낌으로 써도 사용은 가능하지만 필자생각에는 자바때의 interface의 역활에서 훨씬 좋아졌다고 할 수 있다.

package shape

interface Shape {
var x: Int
var y: Int
var width: Int
var height: Int

fun setBounds(x: Int, y: Int) {
this.x = x
this.y = y
}

fun setSize(width: Int, height: Int) {
this.width = width
this.height = height
}

fun getArea(): Float
}

인터페이스 이놈이 변수를 가질 수 있다. 똑똑히 보면 알겠지만. var이다.

정말 변수다. 또한 함수 역시 몸체를 가질 수 있다.

물론 getArea처럼 몸체를 선언하지 않을 수도 있다.

오랬동안 자바만 하던 사람입장에서는 뭐지? 싶을 것이다.

이게 문법적으로 되는건가? jvm에서는 어떻게 인식할까? 한번 확인해보자.


실제로는 모드 abstract다. 또한 당연히 필드역시 선언될 수없다. 즉 실제로는 페이크라는 것이다.

어쨋던 과거 IDE가 하던작업을 이제 interface문법으로 해주는것이라고 생각하면된다.

필자 생각에는 자바의 interface는 특유의 제약때문에 사용하기 힘들었으나 코틀린의 interface가 훨씬 interface답다고 생각한다.

그럼 상속받아서 한번 사용해 보자.

package shape

class Circle(x: Int, y: Int) : Shape {
override var x: Int = x
override var y: Int = y
override var width: Int = 0
override var height: Int = 0
val PI = 3.14f

constructor(x: Int, y: Int, width: Int, height: Int) : this(x, y) {
this.width = width
this.height = height
}

override fun getArea(): Float {
return width / 2 * width / 2 * PI
}
}

오히려 이게 더 직관적인거 같긴하다. 이제 interface의 필드는 상속받으려면 마찬가지로 override를 써야한다.

다행이도 interface의 필드들은 무조건 문법에 의해 override해야하는 의무가 생긴다.

그러면 다중상속 문제가 또 발생할 수 있을것이라 생각한다. 이럴때는 어떻게 해야하는가?

예를들어 아래의 코드를 보자.

package shape

interface Point {
var x: Int
var y: Int

fun setBounds(x: Int, y: Int) {
this.x = x
this.y = y
}
}

Point라는 interface를 동식에 상속받는다면 메소드명이 겹치게된다.

이를 해결하려면 어떻게 할까? 이 방법에 대해서는 새로운 해결책을 제시하고 있다.

package shape

class Circle(x: Int, y: Int) : Shape,Point {

override var x: Int = x
override var y: Int = y
override var width: Int = 0
override var height: Int = 0
val PI = 3.14f

constructor(x: Int, y: Int, width: Int, height: Int) : this(x, y) {
this.width = width
this.height = height
}

override fun getArea(): Float {
return width / 2 * width / 2 * PI
}

override fun setBounds(x: Int, y: Int) {
super<Point>.setBounds(10,20);
super<Shape>.setBounds(10,20);
}
}

일단 동일한 메소드가 각각의 interface에 있다면 모호성 해결을 위해서 자식클래스에서의 오버라이딩이 강제된다.

이때 둘중 하나를 선택하거나 둘다를 쓰거나 완전 다른 방법을 쓰거나하는건 자신의 마음대로이다.

이때는 무조건 명시적으로 부모를 선어해줘야한다. 아래 코드를 보면 super<Point>라는 구문이 있다.

이 구문은 Point형의 setBounds를 긁어서 사용한다. 이런식으로 모호성을 피해가도록 하였다,

사실 자바에서는 어짜피 abstract는 내용이 없으므로 모호성을 해결할 수 있었기 때문에 별 상관없는 관심사였지만.


'Programming > Kotlin' 카테고리의 다른 글

[Kotlin-09]sealed class  (0) 2017.11.10
[Kotlin-08]data class  (0) 2017.11.10
[Kotlin-06]상속(abstract class)  (0) 2017.11.10
[Kotlin-05]상속(open class)  (0) 2017.11.10
[Kotlin-04]open  (0) 2017.11.10

+ Recent posts