Do it! 코틀린 프로그래밍 [둘째마당, 객체 지향 프로그래밍] 학습
객체 지향 프로그래밍 (OOP: Object-Oriented Programming) 은 프로그램의 구조를 객체 간 상호작용으로서 표현하는 프로그래밍 방식으로, 절차적 프로그래밍의 한계를 극복하고자 나온 방법론
📍 절차적 프로그래밍? 코딩한 순서대로 프로그램이 수행될 수 있도록 작성하는 방법론. 단순하고 오류를 예측하기 쉽지만 구조적이지 못해 복잡한 프로그램을 설계하기 어려움
📌객체 지향 프로그래밍의 용어 정리
코틀린 | 다른 언어 |
---|---|
클래스(Class) | 분류, 범주 |
프로퍼티(Property) | 속성(Attribute), 변수(Variable), 필드(Field), 데이터(Data) |
메서드(Method) | 함수(Function), 동작(Operation), 행동(Behavior) |
객체(Object) | 인스턴스(Instance) |
📌 클래스의 멤버가 될 수 있는 것
📌 클래스 다이어그램
📌 추상화 (Abstraction)
📌 클래스 선언하기
⬇️ 클래스 구조
class bird{} // 내용이 비어 있는 클래스 선언
class bird // 중괄호 생략 가능
class bird{
// 프로퍼티
// 메서드
}
⬇️ 클래스 선언과 객체 생성
class Bird {
var name: String = "bird"
fun fly() = println("bird $name")
}
fun main() {
val coco = Bird() // 클래스 생성자를 통한 객체의 생성
println("$coco.name") // 객체의 멤버 프로퍼티 읽기
coco.fly() // 객체의 멤버 메서드 사용
}
📌 객체와 인스턴스 정리하기
클래스를 통해 객체가 만들어질 때 기본적으로 호출되는 함수를 생성자 라고함
⬇️ 생성자 선언
class 클래스 이름 constructor(필요한 매개변수..) { // 주 생성자 위치
...
constructor(필요한 매개변수..) { // 부 생성자 위치
// 프로퍼티(변수) 초기화
}
}
class Bird {
var name: String // 프로퍼티(변수)
var wing: Int
var beak: String
// 부 생성자 - 매개변수를 통해 초기화할 프로퍼티에 지정
constructor(name: String, wing: Int, beak: String) {
this.name = name // this.name 은 현재 클래스의 프로퍼티를 나타냄
this.wing = wing
this.beak = beak
}
}
⬇️ this 키워드를 사용하지 않는 방법
class Bird {
var name: String // 프로퍼티(변수)
var wing: Int
var beak: String
constructor(_name: String, _wing: Int, _beak: String) {
name = _name // name : 클래스의 프로퍼티, _name : 생성자의 매개변수
wing = _wing
beak = _beak
}
}
-> 프로퍼티와 매개변수를 구분하기 위해 다른 이름을 사용
-> 매개변수 이름 앞에 언더스코어(_) 사용
⬇️ 매개변수가 다르게 부 생성자를 여러개 선언
class Bird {
constructor(_name: String, _wing: Int, _beak: String) {
name = _name // name : 클래스의 프로퍼티, _name : 생성자의 매개변수
wing = _wing
beak = _beak
}
// 매개변수가 다른 또 다른 부 생성자
constructor(_name: String, _wing: Int){
name = _name
wing = _wing
beak = "short"
}
}
fun main() {
val coco = Bird("coco", 2, "short")
val noBeak = Bird("coco", 2)
}
// 주 생성자 선언
class Bird constructor(_name: String, _wing: Int, _beak: String) {
var name: String // 프로퍼티(변수)
var wing: Int
var beak: String
}
// constructor 키워드 생략 가능
class Bird(_name: String, _wing: Int, _beak: String) {
var name: String // 프로퍼티(변수)
var wing: Int
var beak: String
}
// 내부의 프로퍼티를 생략하고 생성자의 매개변수에 프로퍼티 선언
class Bird(val name: String, val wing: Int, val beak: String) { }
📌 초기화 블록을 가진 주 생성자
// 주 생성자 선언
class Bird(var name: String, var wing: Int, var beak: String) {
// 초기화 블록
init{
println("---초기화 블록 시작---") // (1)
}
}
fun main() {
val coco = Bird("coco", 2, "short")
// 객체 생성과 함꼐 초기화 블록이 수행
// (1) 문구가 출력
}
📌 프로퍼티의 기본값 지정
// 프로퍼티의 기본값 지정 (name, wing의 기본값을 지정)
class Bird(var name: String = "coco", var wing: Int = 2, var beak: String) { }
fun main() {
// 기본값이 있는 것은 생략, 없는것만 전달 가능
val coco = Bird(beak = "short")
}
자식 클래스를 만들 때 상위 클래스(부모 클래스)의 속성과 기능을 물려받아 계승하는 것
⬇️하위 클래스 선언하기
open class BaseClass(someArgs: Int) // 상속 가능한 클래스
class SomeClass(someArgs: Int) : BaseClass(someArgs) // 클래스 상속의 선언
class SomeClass : BaseClass { ..constructor().. }
이름이 동일하지만 매개변수가 서로 다른 형태를 취하거나 실행 결과를 다르게 가질 수 있는 것
📌 오버로딩(Overloading)
fun add(x: Int, y: Int): Int {
return x + y
}
// 자료형이 다름
fun add(x: Double, y: Double): Double {
return x + y
}
// 매개변수의 개수가 다름
fun add(x: Int, y: Int, z: Int): Int {
return x + y + z
}
📌 오버라이딩(Overriding)
// 부모 클래스
open class Bird{ // 상속 가능
fun fly() { ... } // 최종 메서드로 오버라이딩 불가
open fun sing() { ... } // 오버라이딩 가능
}
// 자식 클래스
class Lark() : Bird() {
fun fly() { /* 재정의 */ } // !오류! fly()는 open키워드 X
override fun sing() { /* 재정의 */ } // 오버라이딩 가능
}