코틀린(Kotlin) 클래스
Notepad96
·2020. 9. 18. 19:47
1. 객체(Object)
서로 관련이 있는 속성(변수)들을 묶어 놓음으로써 고유한 속성들을 갖는 데이터 타입(객체)을 만들어 내는 것.
val book = object {
var name = "Horror Stories"
val price = 32_000
}
book.name = "Horror Stories3"
// book.price = 25_000 val error
println(book.name)
println(book.price)
속성들도 마찬가지로 var로 선언한 name은 값을 변경 할 수 있지만 val로 선언한 price는 값을 변경하고자하면 에러가 발생한다.
객체의 속성들은 '.속성이름' 으로 접근할 수 있다.
2. 클래스(Class)
위에서 book이라는 객체(object)를 만들었다.
만약 이 book이라는 객체가 여러 개가 필요하다면 그만큼 생성하는 똑같은 코드를 여러 개 선언해야 한다.
또한, 속성의 수정 사항이 있을 시 일일이 다 변경해줘야하는 번거로움이 있다.
이러한 문제들을 해결하기 위하여 클래스(class)를 선언하여 사용한다.
클래스는 객체의 껍데기만을 만들어 놓음으로써 더욱 효율적으로 객체를 생성하고 관리할 수 있도록 만든다.
클래스 이름은 관례적으로 대문자로 시작한다.
class Book {
var name: String = "Horror Stories"
var price: Int = 0
fun info() {
println("name: ${this.name}, price: $price")
}
}
var book = Book()
book.name = "Horror Stories2"
book.price = 32_000
println(book.name)
println(book.price)
book.info()
2-1. 생성자(constructor)
기본 생성자
class Book constructor(var name:String, var price:Int) {}
class Book(var name:String, var price:Int) {
init {
println("init 실행: $name, $price")
}
}
기본 생성자란 클래스 선언 시 같이 선언하는 생성자이다.
constructor는 아래처럼 생략하여 작성할 수 있다.
기존 Java에서도 생성자의 이름은 클래스의 이름과 같았으며 이점의 착안하여 이를 합침으로서 더욱 코드를 간결하게 만들 수 있다.
기본 생성자는 따로 코드블럭이 없으므로 무언가 초기화하는 코드를 실행해야한다면 init 블록을 사용해주면 된다.
init 블록은 클래스 생성 시 가장 먼저 실행되며 생성자로 받은 인수들의 접근할 수 있다.
init 블록은 여러 개 존재할 수 있으며 실행 순서는 선언한 순서대로 실행된다.
보조 생성자
class Book(var name:String, var price:Int) {
init {
println("init 실행: $name, $price")
}
constructor() : this("empty", 55_000)
}
var book = Book()
var book2 = Book("Horror Stories2", 12_000)
기본 생성자 외에 다른 형태의 생성자가 필요할 경우 보조 생성자를 선언하여 다른 형태로 클래스를 호출하여 객체를 생성할 수 있다.
※ 동일한 이름의 다른 매개변수를 같는 것을 오버로딩(overloading) 이라고 한다. 이는 생성자 오버로딩
위 코드에서는 매개변수가 없는 보조 생성자를 선언하여서 name= "empty" 로 price = 55000으로 초기화되도록 만들었다.
(이 같은 경우에는 디폴트(default) 매개변수를 사용하면 되므로 굳이 보조 생성자를 생성할 필요가 없다.)
보조 생성자는 기본 생성자와는 달리 코드 블록을 만들 수 있으므로 따로 init블록 없이 초기화 할 수도 있다.
물론 위에서는 init블록이 존재하므로 보조 생성자를 사용하여 객체를 생성하여도 init 블록이 먼저 실행된다.
2-2. Getter / Setter
프로퍼티마다 정의
class Book {
var name = "default"
get() {
println("값 = $price")
return field
}
set(value) {
field = value
}
val price = 0
get() {
return field
}
/*
set(value) {
field = value
}
*/
}
name과 price 프로퍼티 아래 get()과 set(value)을 각각 선언해준 것을 볼 수 있다.
여기서 price는 val을 사용하여 선언하였으므로 불변의 값 즉, 읽기전용의 값이 되므로 set(value)을 작성하면 에러가 발생한다.
get과 set 안에서는 각각 해당하는 필드에 접근하고자 하면 field를 사용하면 접근할 수 있으며 다른 프로퍼티는 변수명을 사용하여 접근할 수 있다.
단, default getter/setter이 존재하여 getter/setter를 선언하지 않을경우 자동으로 정의되므로 추가적인 동작이 필요한 것이 아니라면 작성할 필요없다.
※ 필드(field)와 프로퍼티(property)
자바에서 필드라하면 클래스가 갖는 멤버변수를 가리킨다.
코틀린에서는 이를 프로퍼티라고 정의하는데 그 이유는 프로퍼티는 단순히 필드뿐 아니라 getter/setter의 개념을 포함하고 있기 때문이다.
따라서 위 코드를보면 각 get/set 내부에서는 해당 값에 접근하기 위해서 필드(field)로 접근하는 것을 볼 수 있다.
오버로딩하여 get/set 정의
class Book(var name: String, var price: Int) {
operator fun get(pos:Int):Any {
return when(pos) {
0 -> name
1 -> price
else -> 0
}
}
operator fun set(pos:Int, value:String) {
when(pos) {
0 -> name = value
1 -> price = value.toInt()
}
}
}
이 방법은 '[ ]' 연산자를 오버로딩함으로써 getter/setter 처럼 사용하는 방법이다.
접근할 때는 인덱스를 사용하여서 접근한다. 예를들어 Book book이 있을 경우
'book[1]' -> price get
'book[0] = "new_name"' -> name set
이같이 동작한다.
3. 상속(Inheritance)
상속은 기존 클래스를 확장하여 다른 고유한 것, 클래스를 정의하는 방법이다.
open class Book(var name: String, var price: Int)
class FavBook(name: String, price: Int, var reason:String) : Book(name, price)
var book = Book("Horror Stories", 24000)
var fbook = FavBook("Horror Stories2", 12000, "fun")
상속은 기본적으로 못하도록되어 있기 때문에 class 앞에 open 키워드를 붙여 열어줌으로써 상속을 허용할 수 있다.
해당 코드는 Book 클래스를 상속받는 FavBook 클래스를 정의하는 것을 볼 수 있다.
상속을 사용함으로써 중복되는 코드를 줄일 수 있으며 클래스간 연관성을 직관적으로 확인할 수 있다.
다중 상속은 불가능하여 상속은 한개의 클래스만 가능하다.
3-1. 오버라이딩(overriding)
상속 관계에 있는 클래스에서 다른 동작을하여 메소드를 재정의 할 필요가 있을 때 사용할 수 있다.
(직접 수정해보며 실행해볼 수 있다. 로드가 안된다면 새로고침 or play.kotlinlang.org/)
메소드를 재정의 하기 위해서는 부모 클래스에서 재정의할 메소드의 open 키워드를 붙여 열어주어야 한다.
코틀린에서는 재정의 할 메소드의 앞에는 override 키워드를 붙이게함으로써 더욱 안정성을 높이었다.
자식 클래스에서 super 키워드를 사용하여 부모클래스의 접근할 수 있다.
3-2. 클래스 타입 비교 is
클래스 타입을 비교하기 위해서 is 연산자를 사용한다. 이는 자바의 instanceof 같은 것이다.
var book = Book("Horror Stories", 25000)
var fbook = FavBook("Horror Stories2", 12000, "fun")
println(book is Book)
println(fbook is Book)
println(book is Any)
결과는
book은 Book 클래스로 생성한 것이므로 => true
fbook은 Book 클래스를 상속받은 FavBook으로 생성한 것이므로 => ture
Any는 모든 클래스의 최상위 클래스이므로 => true
이다.
4. 참 조
'Kotlin > Syntax' 카테고리의 다른 글
Kotlin 접근 지정자(= 가시성 지정자, Visibility Modifiers) (0) | 2020.10.01 |
---|---|
Kotlin null, nullable 타입 (0) | 2020.09.23 |
Kotlin 예외(Exception) 처리 (0) | 2020.09.21 |
코틀린(Kotlin) 제어문(for, if, when, while) (0) | 2020.09.17 |
코틀린(Kotlin) 기본 문법(자료형, 형변환, 배열) (0) | 2020.09.15 |