✏231120 월요일 TIL(Today I learned) 오늘 배운 것
📖클래스의 생성자(constructor)
- constructor는 클래스를 사용하기 위한 일종의 함수이다.
1. Primary Constructor
class Name (value: String) {
init {
Log.d("class", "생성자로부터 전달받은 값은 ${value}입니다.")
}
}
- 위의 코드에서 ( )괄호안에 들어있는게 생성자이다. constructor가 ( )앞에 생략되어있는 모습이며, 클래스 명 옆에 바로 붙어있는 생성자를 Primary constructor(주 생성자, 프라이머리 생성자)라고 한다.
-
※constructor를 생략할 수 없는 경우가 있다.
Primary Constructor가 어노테이션이나 접근제어자를 가진 경우에는 생략이 불가능하다.
-
기본생성자를 호출하면 init 코드 블록이 실행된다.
-
init블록은 생성자의 인자로 들어온 값을 검증하고 주입하는 초기화 작업을 한다. (초기화 작업이 필요하지 않다면, init 블록을 꼭 작성하지 않아도 된다.)
-
init블록은 생성자를 통해 넘어온 파라미터에 접근이 가능하다.
class Name (val value: String) {
fun process() {
print(value)
}
}
- 생성자에서 파라미터 앞에 프로퍼티 키워드 val을 붙여주면 클래스 안에서 해당 파라미터를 사용할 수 있다. (var보다는 읽기전용 val 사용 권장)
class Name {
}
- 생성자를 작성하지 않는 경우도 있다. 이런 경우 Default 생성자라고 한다.
- 파라미터가 없는 Primary 생성자가 하나 있는 것과 동일한 경우이다.
2. Secondary Constructor
class Name {
constructor (value: String){
}
constructor (value: Int){
}
constructor (value1: Int, value2: String){
}
}
- constructor 키워드를 함수처럼 클래스 안에 직접 작성 가능한 것이 Secondary constructor(부 생성자, 세컨더리 생성자)이다.
- 여러개를 중복해서 만들기 가능.
📖클래스의 사용
Name()
var name = Name()
- 클래스 이름에 괄호를 붙여서 직접 클래스 생성자 호출이 가능하다.
- 이렇게 클래스 생성자를 호출하여 생성된 인스턴스를 프로퍼티에 담아둘 수 있다.
class Name {
fun printName(){
}
}
name.printName()
- 클래스의 사용 = 클래스 내부에 정의된 프로퍼티와 메서드를 사용한다.는 뜻이다.
내부에 정의된 프로퍼티와 메서드는 .(도트 연산자)로 접근할 수있다.
- 참고로 세컨더리 생성자에서는 init(초기화)블록이 먼저 실행되고 constructor블록 코드가 그 다음 실행된다.
📖오브젝트와 데이터 클래스
1. Object (오브젝트)
object Name {
fun printName(){
}
}
Name.printName()
- 인스턴스화 하지 않아도 블록안의 프로퍼티와 메서드를 호출할 수 있다.
(Java에서 static 역할)
- 마찬가지로 .(도트 연산자)를 사용하여 생성자 없이 직접 호출할 수 있다.
(※ 클래스 그대로 사용하는 것이기 때문에 클래스명의 첫 글자를 대문자로 사용하는 것 주의.)
- 클래스와 다르게 앱 전체에 1개만 생성된다.
2. companion object (컴패니언 오브젝트)
class Name {
companion object {
fun printName() {
}
}
fun selectName() {
}
}
Name.printName()
val newName = Name()
newName.selectName()
- 일반 클래스에 object 기능을 추가할 때 companion object를 사용한다.
- 컴패니언 오브젝트 블록 안에서 변수와 함수를 정의하면 생성자를 통하지 않고 클래스의 멤버들을 사용할 수 있다.
- 컴패니언 안의 코드를 사용할 때는 object사용법에 맞춰서 첫글자 대문자에 유의하여 사용하면 된다.
- 컴패니언 오브젝트 바깥의 일반함수도 일반 함수 사용법에 맞춰서 사용하면 된다.
3. 데이터 클래스
data class 클래스명(val 파라미터1: 타입, var 파라미터2: 타입) {
}
- 간단한 값의 저장 용도로 사용한다.
- data 키워드와 val(var) 키워드는 생략할 수 없다.
- 일반 클래스와 동일하게 생성자 호출하면 init블록도 동작하고, 메서드도 사용 가능하다.
- 데이터 클래스에서 toString( ) 메서드를 사용하면 인스턴스 주소값이 아니고, 실제 값을 반환한다.
- copy( ) 메서드로 복사가 가능하다.
- 이외에도 hashcode(), equals(), componentN()의 함수들이 기본적으로 제공 된다.
📖클래스의 상속
1. 상속
- 클래스의 재사용을 위한 상속. 체계적 관리가 가능해진다.
- ACtivity 클래스 내부에 미리 정의 되어있는 기능을 사용하여 직접 구현하지 않아도 필요한 기능을 추가할 수 있다.
- 생성자 또는 초기화 블록에서 사용되는 프로퍼티에는 open사용 피하기.
(상위 클래스의 생성자에 접근하게 되거나 init의 경우 하위클래스 final이 아닌 오바라이드 필드에 접근하게 될 수 있기 때문이다.)
open class Parent {
open var opened: String = "I am"
open fun opened() {
}
fun notOpened(){
}
}
class Child : Parent() {
override var opened: String = "You are"
override fun opened(){
}
}
- 코틀린에서는 open 키워드를 사용해서 열어줘야지만 자식 클래스에서 상속 받을 수 있다.
- 부모 클래스에서 정의된 프로퍼티와 메서드를 자식 클래스에서 자기 것 처럼 사용 할 수 있다.
- 세컨더리 생성자 또한 오버라이딩으로 여러개 중복해서 사용할 수 있다. (super 키워드로 전달)
2. 익스텐션(Extension) 지원.
- 이미 만들어져 있는 클래스에 메서드를 추가하는 것. (확장)
fun 클래스.확장할 메서드(){
}
- 누군가 작성해두거나, 이미 컴파일 되어 있는 클래스에 매서드를 추가하기 위한 용도로 사용하는 것이 적절하다.
- 실제 클래스의 코드가 변경되는 것은 아니다. 클래스 안에 메서드를 구현해서 사용하는 것처럼 만들어주는 효과가 있는 것이다.
- 이렇게 확장한 함수는 override 불가능 매개변수 타입이 다르면 오버로드는 가능.
✏오늘 발생 문제 및 해결
📖새롭게 알게 된 것
-
오브젝트와 컴패니언 오브젝트의 경우는 코틀린에서 처음 보는 형태였다.
그래도 자바에서 static 역할을 한다고 했으니까 아예 낯선 기능은 아닌 것 같다.
-
데이터 클래스의 경우도 형태는 처음이나, DTO역할을 해줄 수 있는 기능 같다.
-
=> 위의 두가지 사항에 대해 앞으로 실제 실무에서 적용해보면서 생각한 것 처럼 사용되는지 확인할 것이다.
📖오늘의 문제 발생
기본 문법서를 읽는 중에 모르거나 부정확하게 알고 있는 단어들이 많이 나왔다.
프로퍼티와 변수 같이 비슷한 뜻의 단어를 명확히 구분 짓지 않고 멋대로 읽는 버릇을 고쳐야 겠다.
📖해결
일단 구글링을 해가면서 보충하고, 다시 한 번 확실하게 정의해가며 이해했다.
그 내용들은 일단 오늘 배운 것들에 추가하여 한꺼번에 작성했다.
클래스 내부에 정의되는 프로퍼티 함수 안에 정의되는 변수를 구분하여 사용하는 것에 의식을 해야겠다.
✏같이 보면 좋은 글
- 객체지향 프로그래밍 (OOP)
- 상속과 관련된 오버라이딩, 실드클래스
- 인터페이스 (interface)
- 오버로딩