메소드 설계
메소드란? : 특정한 로직을 가지는 소스코드에 이름을 붙이는 것.
- 코틀린에서는 항상 프로그램이 main 에서 시작함.
- 반환자료형이 없는 경우에는 Unit 으로 명시하거나 생략 가능.
- 메소드의 사용을 호출이라고 부름.
Kotlin의 메소드 구조
fun 메소드 이름(변수명: 자료형, 변수명: 자료형 ... ): 반환자료형 {
소스코드 로직
}
클래스 설계
객체 지향 프로그래밍?
- Object Oriented Programming (OOP)
- 코틀린은 모든것이 클래스 형태이므로 객체화 가능, 필요한 데이터를 추상화시켜 상태와 행위를 가진 객체를 만듬.
- 객체들간의 적절한 결합을 통해 유지보수를 쉽게 함.
- 5대 키워드 : 클래스, 추상화, 캡슐화, 상속, 다형성
참고자료 : 객체 지향 프로그래밍 / 절차 지향 프로그래밍 / 함수형 프로그래밍
클래스란?
- 프로그램의 각 요소별 설계도, Kotlin에서는 class 키워드를 활용해서 클래스를 만듬.
- 클래스에는 하나의 정보(프로퍼티)와 행위(메소드)를 작성함.
- 보통 하나의 파일은 한개의 클래스를 의미하나, 하나의 파일에 여러 클래스가 존재하기도 함.
Kotlin의 클래스 구조
class 클래스이름 {
정보1
정보2
행위1
행위2
}
데이터 클래스 (data class) : 정보(프로퍼티)만 갖고 있는 클래스가 필요할 때 사용함.
기본 생성자에 1개 이상의 매개변수가 변수나 상수로 존재해야 함.
실드 클래스 (sealed class) : 상속받을 수 있는 자식클래스를 미리 정의 가능, 무분별한 상속 방지.
컴파일 시점에 생성할 수 있는 자식을 알수있어서 효율적으로 다형성 구현.
sealed class 부모클래스 {
class 자식클래스1 : 부모클래스생성자
class 자식클래스2 : 부모클래스생성자
}
오브젝트 클래스 (object class) : Java의 static 대신 사용하는 키워드, 프로그램을 실행하는 동시에 인스턴스화.
열거 클래스 (enum class) : 상수값에 대한 관리지점을 줄이는게 가능.
Comparable 인터페이스를 구현하는 추상 클래스.
enum class 클래스1 {
C, JAVA, KOTLIN
}
enum class 클래스2(val code: Int) {
C(10),
JAVA(20),
KOTLIN(30)
}
fun main() {
println(클래스1.C.toString()) // 출력: C
println(클래스2.KOTLIN.code) // 출력: 30
println(클래스2.KOTLIN.name) // 출력: KOTLIN
}
유용한 메소드를 자동으로 생성
- hashCode() : 객체를 구분하기 위한 고유값 리턴
- equals() : 동일한 객체인지 비교해서 true 또는 false 로 리턴해줌.
- copy() : 현재 객체의 모든 정보를 복사한 새 개체를 리턴해줌.
- toString() : 현재 객체의 모든 정보(프로퍼티)를 출력해줌.
- get___() / set___() : 변수의 값을 리턴하거나 설정해줌.
생성자의 활용
생성자란?
주 생성자 (Init) :
클래스 선언부에 생성자를 명시하나, 매개변수를 직접 넘기지는 않음.
한 가지의 형태로 클래스를 실체화 할 때 활용 가능.
부 생성자 (Constructor) :
명시적 생성자. _xxx와 같이 생성자에 변수를 넘기는 경우에 사용함.
여러 형태로 클래스를 실체화 할 때는 보조 생성자 활용 가능.
객체의 활용
객체란? : 모든 인스턴스를 포함하는 개념, 클래스 타입으로 선언된 것들을 객체(Object)라고 함.
인스턴스란? : 클래스 형태로 설계된 객체를 실체화하면 인스턴스가 생성, 인스턴스는 메모리 공간을 차지함.
클래스의 실체화란? : 정보와 행위를 작성한 클래스를 실체화 해서 프로그램에 로딩 (메모리에 적재)
정보와 행위가 아닌 위치정보를 메모리에 로딩함.
프로그램은 객체의 위치정보를 변수에 저장해두고 필요할때 참조함.
상속
클래스의 상속이란?
- 클래스(설계도) 간의 관계를 더욱 끈끈하게 만들 수 있음.
- 공통요소가 있다면 부모, 자식 클래스를 구분해서 상속관계 가능.
- Kotlin은 생략된 final 키워드로 기본상태에서는 상속을 막아둠, 무분별한 상속 방지.
- open 을 통해 상속관계 생성 가능.
상속의 사용법은? : 다형성 구현 가능, 클래스 내용 변경 시 부모클래스만 변경하여 수고를 줄임.
부모 클래스에서 생성자를 활용하는 경우, 자식에게서 객체 생성시 전달해줘야 함.
예시 코드
fun main() {
var bird = Bird("새")
brid.fly()
}
// 부모 클래스
open class Bird(name: String) {
var name: Stirng = ""
init {
// this 는 현재 클래스의 상태변수를 의미
// var name: String = ""
this.name = name
}
fun fly() {
println("${name}가 날아갑니다.")
}
}
class Chicken : Bird() {
}
오버라이딩
오버라이딩이란?
상속받은 부모 클래스의 정보(프로퍼티)나 행위(메소드)를 재설계 가능. 주로 부모 클래스의 메소드를 재설계.
오버라이딩을 하는 이유?
OOP 관점에서는 클래스들간의 관계를 만들어 일관성을 유지하는게 목표.
필요기능이 생길때마다 별도로 만들면 일관성을 유지할 수 없음. 재사용성이 떨어져 유지보수가 어려움.
유용한 단축키 : 자식 클래스 내부에서 Control + O (Windows) 사용
예시 코드
fun main() {
var bird = Bird("새")
var chicken = Chicken("닭", 2)
bird.fly()
chicken.fly()
}
open class Bird(name:String) {
var name: String = ""
init {
// this는 현재 클래스의 상태변수를 의미합니다
// var name: String = ""
this.name = name
}
open fun fly() {
println("${name}은 날아요~")
}
}
class Chicken(name: String, age: Int) : Bird(name) {
var age:Int = 0
init {
this.age = age
}
override fun fly() {
// super객체는 부모의 객체를 의미하며 자동으로 생성됨
// 즉 부모객체의 fly메소드를 부르는 행위임
// 필요없으니 주석처리완료
// super.fly()
println("${age}살의 ${name}가 날아봅니다~ 꼬끼오!")
}
}
오버로딩
매개변수의 갯수, 또는 자료형을 다르게 하면 동일한 이름의 메소드를 여러 형태로 만들 수 있음.
반환자료형(반환형)은 오버로딩에 영향을 주지 않음.
예시 코드
fun main() {
var calc = Calculator()
var intResult = calc.add(1,2)
var doubleResult = calc.add(1.2, 2.2)
println("정수 덧셈결과: ${intResult}")
println("실수 덧셈결과: ${doubleResult}")
}
class Calculator {
fun add(num1: Int, num2: Int): Int {
return num1+num2
}
fun add(num1: Double, num2: Double): Double {
return num1+num2
}
}
인터페이스
Kotlin은 부모 클래스는 반드시 하나뿐이라 모두 상속으로 처리가 불가능함.
따라서 근본적인 공통점을 상속받고 추가적인 기능들은 인터페이스로 만듬. interface 키워드 사용.
인터페이스의 구조
아래처럼 메소드의 로직이 존재하지 않고 이름만 존재하면 추상메소드라고 함.
원래 인터페이스는 추상 메소드만 허용했으나 최근에는 아니어도 됨. 단 추상메소드로 사용하는 습관 권장.
interface 인터페이스이름 {
fun 메소드이름()
}
예시 코드
// WaterBirdBehavior.kt
interface WaterBirdBehavior {
fun swim()
}
// Main.kt
fun main() {
var bird = Bird("새")
var chicken = Chicken("닭")
var duck = Duck("오리")
bird.fly()
chicken.fly()
duck.swim()
}
open class Bird(name:String) {
var name: String = ""
init {
// this는 현재 클래스의 상태변수를 의미합니다
// var name: String = ""
this.name = name
}
fun fly() {
println("${name} 날아요~")
}
}
class Chicken(name: String) : Bird(name) {
}
class Duck(name: String) : Bird(name), WaterBirdBehavior {
override fun swim() {
println("${name}가 수영해요~")
}
}
'Kotlin' 카테고리의 다른 글
Kotlin 4주차 (0) | 2024.02.02 |
---|---|
Kotlin 2주차 (0) | 2023.12.12 |
Kotlin 1주차 (0) | 2023.12.11 |