티스토리 뷰
객체 지향(Object Oriented Programming)
• 객체 지향이란 해결해야 할 문제 또는 원하는 바를 "객체"라는 기본 단위를 통해 해결하는 것을 의미.
• 객체란 하나의 역할을 수행하는 묶음 단위.
• 객체들 간의 상호작용을 통해 프로그램을 만듦.
ex) 고양이 객체, 쥐 객체 생성. 고양이 객체에 할퀴는 기능 구현, 쥐 객체에 도망치는 기능 구현.
• 객체 지향을 잘 하는 법
- 객체를 어떻게 구성하는 지가 개발을 잘 하는 방법이자 노하우.
- 개념적, 문법적 지식도 중요하지만 경험이 정말 중요!! -> 하루 아침에 잘 해질 수 없다.
ex) 축구 게임을 만든다고 가정
- 개발자 A : 축구 선수, 심판, 경기장, 관중 객체를 생성
- 개발자 B : 사람, 공, 호루라기, 경기장 객체 생성
- 개발자 A와 B 중에 누가 더 좋은 코드인가? -> 많은 경험을 통해 판별 가능.
클래스(Class)
• 클래스란 객체를 만드는 문법적인 요소.
- 코틀린은 객체 지향 언어이므로 객체를 만들어내는 이 '클래스'라는 문법이 코틀린에서 매우 중요하다.
• 클래스는 객체를 만들어내는 틀.
- 클래스로 만들어질 객체가 어떠한 속성, 기능 등을 가질 것일지 작성.
- 그 후 해당 클래스로 만든 객체는 작성한 속성과 기능을 가짐.
- 클래스 하나로 여러 객체를 찍어낼 수 있음.
• 객체의 설명서 역할
- 클래스 안에는 이 클래스로 객체를 만들 때 필요한 재료, 객체가 사용할 수 있는 기능, 속성 등이 적혀있다.
• 클래스는 하나의 자료형으로 사용할 수 있다.
- 어떤 클래스로 만들어진 객체의 자료형은 해당 클래스가 된다.
• 클래스 이름은 대문자로 시작하는 것이 좋다.
• class 클래스명 {
내용
}
class Person { // Person이라는 클래스 생성
// Person 클래스로 객체를 만들기 위한 규칙 정하는 코드
// Person 클래스로 만들어낼 객체가 가질 속성, 기능 코드
}
val person: Person = Person() // person 변수를 Person 클래스의 객체로 선언. person의 자료형은 Person이다.
프로퍼티 & 메소드
• 객체가 사용할 수 있는 속성은 변수 형태로 저장된다.
- 이를 프로퍼티(Property)라고 한다.
• 객체가 사용할 수 있는 기능은 함수 형태로 저장된다.
- 이를 메소드(Method)라고 한다.
• 사람이란 틀을 만들어서 이름, 나이라는 속성이 있고, 걷기라는 기능이 있는 객체를 만든다고 해보자.
- Person이라는 클래스 안에 name, age라는 프로퍼티, walk()라는 메소드를 생성.
• 객체 생성 시 실행되는 초기화 블록 init이 있다.
- 코틀린에서는 변수 선언 시 기본적으로 초기값도 같이 할당해주어야 한다.
ex) val num1 // 오류 발생 : 변수 선언 시 초기값도 할당해야 함.
ex) val num2 = 10 // 선언 시 초기값도 같이 할당
- 프로퍼티도 변수이기 때문에 초기값을 할당해주어야 한다.
- 클래스에서 초기화 과정은 init 블록 안에서 진행 된다.
class Person2 {
var name: String // 이름이란 속성을 name 프로퍼티로 생성
var age : Int // 나이란 속성을 age 프로퍼티로 생성
init {
// 프로퍼티 초기화
name = "홍길동"
age = 20
// 그 외 객체 생성시 필요한 행동
println("그 외 필요한 행동")
}
fun walk(): Unit { // 걷기라는 기능을 walk() 메소드로 생성
println("걷는다.")
}
}
val person2: Person2 = Person2() // Person2 클래스를 이용하여 person2 객체 생성
println(person2.name) // 홍길동 출력
println(person2.age) // 20 출력
person2.walk() // 걷는다 출력
• 하지만 위의 코드는 객체를 몇 개를 만들어도 name은 홍길동이고 age는 20인 똑같은 객체만 만들어진다.
val person2_2: Person2 = Person2()
val person2_3: Person2 = Person2()
val person2_4: Person2 = Person2()
println(person2_2.name, person2_2.age) // 홍길동20 출력
println(person2_3.name, person2_3.age) // 홍길동20 출력
println(person2_4.name, person2_4.age) // 홍길동20 출력
-> 클래스 외부에서 재료를 받아와서 재료에 맞게 클래스 내부를 만들어야 한다.
생성자
1. 주 생성자(Primary Constructor)
• 클래스로 객체를 만들 때 필요한 재료들을 적는 곳.
- 재료를 인자로 받아 클래스를 구성하는 데에 사용한다.
• 클래스를 선언할 때, 클래스명 옆에 명시
• constructor 키워드를 사용.
class Person3 constructor(personName: String, personAge: Int) { // personName과 personAge라는 재료를 받는다.
var name: String
var age: Int
init {
name = personName // name 프로퍼티에 생성자가 받은 재료인 personName 저장
age = personAge // age 프로퍼티에 생성자가 받은 재료인 personAge 저장
}
fun walk() {
println("걷는다.")
}
}
// 원하는 재료를 넣어 객체 생성
val person3_1: Person3 = Person3("홍길동", 20) // person3_1 객체는 name이 홍길동, age가 20인 객체
val person3_2: Person3 = Person3("고길동", 40) // person3_2 객체는 name이 고길동, age가 40인 객체
val person3_3: Person3 = Person3("김길동", 32) // person3_3 객체는 name이 김길동, age가 32인 객체
val person3_4: Person3 = Person3("이길동") // 오류 발생 : 필요한 재료를 모두 넣지 않았을 경우
• constructor 키워드는 생략 가능.
// 객체 생성 시 필요한 재료가 있을 때
class Person4 constructor(personName: String, personAge: Int) { // constructor 키워드 사용
// ~~ 내용
}
class Person5(personName: String, personAge: Int) { // constructor 키워드 생략
// ~~ 내용
}
// 객체 생성 시 재료가 필요 없을 때
class Person6 constructor() { // constructor 키워드 사용
// ~~ 내용
}
class Person7() { // constructor 키워드 생략
// ~~ 내용
}
class Person8 { // 재료가 필요없으면 ()도 생략 가능
// ~~ 내용
}
• 인자의 기본값을 설정하면 객체 생성 시 재료에 값을 넣지 않아도 기본값으로 할당된다.
class Person9(personName: String = "김아무개", personAge: Int = 30) { // personName, personAge의 기본값 설정
val name: String
val age: Int
init {
name = personName
age = personAge
}
}
val person9_1 = Person9("홍길동", 26) // 필요한 인자 모두 넣음
val person9_2 = Person9("홍길동") // 필요한 인자인 personAge 없음 -> personAge = 30
val person9_3 = Person9() // 필요한 인자인 personName, personAge 없음 -> personName = "김아무개", personAge = 30
println(person9_1.name + person9_1.age) // 홍길동26 출력
println(person9_2.name + person9_2.age) // 홍길동30 출력
println(person9_3.name + person9_3.age) // 김아무개30 출력
• 프로퍼티 이름과 인자의 이름을 같게 하고 싶을 때는 this 키워드를 사용하여 두 개의 변수를 구분할 수 있다.
- this 키워드 : 클래스 내부에서 this를 사용하면 해당 클래스, 해당 객체 자기 자신을 의미함.
- 코틀린에서는 프로퍼티와 인자의 이름을 다르게 하는 것을 권장하지만, 자바에서는 둘의 이름을 같게 한 후 this로 구분하는 스타일이 많이 잡혀있었기 때문에 이렇게도 많이 쓴다.
class Person10(name: String, age: Int) {
val name: String
val age: Int
init {
this.name = name // this란 이 객체, this.name이란 이 객체의 name, 즉 프로퍼티 name을 뜻함.
this.age = age // 즉, 프로퍼티 age에 인자로 받아온 age 값을 넣는다는 의미
}
}
val person10: Person10 = Person10("홍길동", 26)
println(person10.name) // 홍길동 출력
println(person10.age) // 26 출력
* 클래스 선언 간단하게 생략하는 법
• init의 생략
- init 블록에서 할 작업이 프로퍼티에 초기값 할당하는 것 밖에 없다면 굳이 init을 사용하지 않고 프로퍼티 생성 시 값 할당을 같이해도 된다.
class Person11 constructor(personName: String, personAge: Int) {
val name: String = personName // name 프로퍼티 생성 시 초기값 할당도 한 번에 처리
val age: Int = personAge // age 프로퍼티 생성 시 초기값 할당도 한 번에 처리
}
val person11: Person11 = Person11("홍길동", 26)
• constructor의 생략
class Person12(personName: String, personAge: Int) { // constructor 키워드 생략
val name: String = personName
val age: Int = personAge
}
val person12: Person12 = Person12("홍길동", 26)
• 인자 생략
- 인자를 받아서 프로퍼티에 바로 넣을 것이라면, 아래와 같이 생략할 수 있다.
class Person13(val name: String, val age: Int) { // 인자 생략
}
val person13: Person13 = Person13("홍길동", 26)
2. 부 생성자(Secondary Constructor)
• 객체를 만들기 위한 필수 조건은 주 생성자에, 선택할 수 있는 사항은 부 생성자에 적는다.
• 부 생성자는 주 생성자에 적은 필수 조건을 포함하고 있어야 한다.
• 클래스를 생성하는 데에 직접 관여하는 것은 주 생성자이다. -> 부 생성자는 주 생성자에게 객체 생성을 위임해야 한다.
• 부 생성자는 클래스의 본문에 위치한다.
• 부 생성자는 복수 개가 가능하다.
class Person14 constructor(name: String) {
val name: String
var age: Int = 0
var gender: String = "남자"
init {
this.name = name
}
// 부 생성자는 클래스의 본문에 위치
// 부 생성자는 필수 조건 name을 반드시 포함
// 부 생성자는 주 생성자에게 클래스 생성을 위임해야 함.
// -> 부 생성자가 인자 name, age를 받아서 this(name)으로 넘겨줌
// -> this가 이 클래스 자신을 나타내므로 this(name)은 곧 Person11(name).
// -> 즉, name을 주 생성자에게 넘겨주고 생성을 위임.
// -> 주 생성자에서는 쓰지 않는 age만 본인이 다룸.,
constructor(name: String, age: Int): this(name) {
// 부 생성자 블록
this.age = age
}
// 부 생성자는 복수 개가 가능하다.
constructor(name: String, age: Int, gender: String): this(name) {
// 부 생성자 블록
this.age = age
this.gender = gender
}
}
val Person14_1 = Person14("홍길동") // 주 생성자만 사용하여 객체 생성
val Person14_2 = Person14() // 오류 발생 : 주 생성자에 필요한 인자가 없으므로
val Person14_3 = Person14("고길동", 50) // 인자가 age까지 있으므로 첫 번째 부 생성자를 사용하여 객체 생성
val Person14_4 = Person14("김길동", 20, "여자") // 인자가 age와 gender까지 있으므로 두 번째 부 생성자를 사용하여 객체 생성
println("" + Person14_1.name + Person14_1.age + Person14_1.gender) // 홍길동0남자 출력
println("" + Person14_3.name + Person14_3.age + Person14_3.gender) // 고길동50남자 출력
println("" + Person14_4.name + Person14_4.age + Person14_4.gender) // 김길동20여자 출력
3. 주 생성자와 부 생성자 코드 실행 순서
• 참고 글 : https://slowsure.tistory.com/21
• 주 생성자를 사용하여 객체를 생성했을 때 코드의 순서
- 주 생성자로 인자를 받아옴 -> 프러퍼티 생성 -> 초기화 함수 실행
• 부 생성자를 사용하여 객체를 생성했을 때 코드의 순서
- 부 생성자로 인자를 받아옴 -> 주 생성자로 인자를 위임함 -> 프로퍼티 생성 -> 초기화 함수 실행 -> 부 생성자 블록 실행
• 유의점
- 코틀린에서 변수는 기본적으로 선언 시 초기값이 할당이 되어야 한다.
- 클래스에서는 프로퍼티 선언 시, 선언과 동시에 초기값을 할당하거나, 초기화 함수를 진행하면서 초기값을 할당해야 한다.
- 보통 부 생성자에서 받은 값을 프로퍼티에 넣는 작업은 부 생성자 블록에서 많이 하는데, (아래와 같이)
class Person15(name: String) {
// 생략
constructor(name: String, age: Int): this(name) {
// 부 생성자 블록
this.age = age // 부 생성자에서 받은 age를 프로퍼티인 this.age에 할당
}
// 생략
}
- 부 생성자 블록의 실행 순서는 맨 마지막이기 때문에, 프로퍼티 생성 후 초기화 함수 실행 전까지 프로퍼티에 초기값이 할당이 되지 않으므로 오류가 발생한다.
- 따라서 부 생성자 블록에서 할당되는 프로퍼티는 생성과 동시에 초기값을 할당해주어야 한다. (위의 Person14 코드 참고)
주 생성자가 없고 부 생성자만 있는 클래스
class Person16 {
val name: String
val age: Int
constructor(name: String, age: Int) {
this.name = name
this.age = age
}
}
val person16_1: Person16 = Person16()
val person16_2: Person16 = Person16("홍길동", 26)
• 주 생성자가 없으면 코틀린에서 자동 생성해준다.
- 인자를 받지 않고 비어 있는 주 생성자를 자동 생성.
• 주 생성자가 명시되어 있지 않기 때문에 생성 위임도 명시하지 않아도 된다.
• 잘 쓰지 않는 방식이다.
클래스로서의 자료형
* 실제로 코틀린에서 사용하는 자료형 Int, String, Boolean 등은 클래스이다.
• 자료형 Int의 선언부에 가보면 Int라는 클래스가 선언되어 있는 것을 알 수 있다.
• 다른 클래스와 마찬가지로 프로퍼티, 메소드 등이 정의되어 있다.
이 글은
패스트 캠퍼스 Android 앱 개발의 정석 with Kotlin 올인원 패키지 Online
강의를 듣고 공부한 내용을 바탕으로 작성되었습니다.
'📱 Android > 💻 Kotlin' 카테고리의 다른 글
[Android/Kotlin] 16. 접근 제한자 (0) | 2022.10.12 |
---|---|
[Android/Kotlin] 15. 클래스 2편 (2) | 2022.10.12 |
[Android/Kotlin] 13. 일급 시민, 고차 함수, 람다식 (0) | 2022.10.07 |
[Android/Kotlin] 12. 출력 (0) | 2022.10.07 |
[Android/Kotlin] 11. 예외 처리 (0) | 2022.10.07 |