[Kotlin] 5. 클래스와 객체
※ “Do it! 코틀린 프로그래밍” 을 참고하여 작성하였습니다.
05-1 클래스와 객체의 정의
- 객체 지향 용어
- 추상화: 특정 클래스를 만들 때 기본 형식을 규정하는 방법
- 인스턴스: 클래스로부터 생성한 객체
- 상속: 부모 클래스의 내용을 자식 클래스가 그대로 물려받음
- 다형성: 하나의 이름으로 다양한 처리를 제공
- 캡슐화: 내용을 숨기고 필요한 부분만 사용
- 메시지 전송: 객체 간에 주고받는 메시지
- 연관: 클래스 간의 관계
- 클래스의 멤버
- 생성자와 초기화 블록: 객체가 생성될 때 자동 실행되는 메서드 또는 코드 블록
- 프로퍼티: 변수의 이름과 변수의 접근 함수가 포함된 혀태
- 메서드: 일반적인 함수의 형태
- 중첩 클래스와 이너 클래스: 클래스 내부에 구성되는 클래스
- 객체 선언(컴패니언 객체): 클래스 없이 접근할 수 있는 객체
- 클래스의 추상화를 코드로 표현하기
- 클래스 정의
- 클래스의 객체를 생성하여 클래스의 프로퍼티와 메서드를 이용
05-2 생성자
생성자: 클래스를 통해 객체가 만들어질 때 기본적으로 호출되는 함수
부 생성자: 클래스 내에 부 생성자 블록을 따로 선언
default
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
class Bird{ var name: String var wing: Int var beak: String var color: String constructor(_name: String, _wing: Int, _beak: String, _color: String){ name = _name wing = _wing beak = _beak color = _color } fun fly()=println("Fly wing: $wing") fun sing(vol:Int)=println("Sing vol: $vol") }
부 생성자 여러 개 사용하기 → 매개변수를 다르게 정의해야 함
주 생성자: 클래스 선언과 동시에 주 생성자 선언
default
- 주 생성자에서의 constructor 키워드는 생략할 수 있음
- 하지만, 클래스에서 가시성 지시자 or 애노테이션 표기가 존재하면 constructor 키워드는 생략할 수 없음
1 2 3 4 5 6 7 8 9 10
class Bird(var name: String, var wing: Int, var beak: String, var color: String){ init{ println("----------초기화 블록 시작----------") println("이름은 $name, 부리는 $beak") this.sing(3) println("----------초기화 블록 끝----------") } fun fly()=println("Fly wing: $wing") fun sing(vol:Int)=println("Sing vol: $vol") }
프로퍼티의 기본값 지정
1 2 3
class Bird(var name: String= "NONAME", var wing: Int= 2, var beak: String, var color: String){ ... }
05-3 상속과 다형성
상속: 자식 클래스를 만들 때 상위 클래스의 속성과 기능을 물려받아 계승
다형성: 메서드가 같은 이름을 사용하지만, 구현 내용이 다르거나 매개변수가 달라서 하나의 이름으로 다양한 기능을 수행할 수 있는 개념
상속과 클래스의 계층
- 최상위 클래스
- 기반 클래스(open 클래스): open 키워드 필수!
- 파생 클래스(최종 클래스): 상속 불가
기반 클래스와 파생 클래스의 구현
- 기반 클래스: Bird 클래스, open 키워드 사용
- 파생 클래스
- Lark 클래스: 주 생성자를 사용하는 상속
- Parrot 클래스: 부 생성자를 사용하는 상속
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
open class Bird(var name: String, var wing: Int, var beak: String, var color: String){ fun fly()=println("Fly wing: $wing") fun sing(vol:Int)=println("Sing vol: $vol") } class Lark(name: String, wing: Int, beak: String, color: String) : Bird(name, wing, beak, color){ fun singHitone()=println("Happy Song!") } class Parrot : Bird { val language: String constructor(name: String, wing: Int, beak: String, color: String, _language: String) : super(name, wing, beak, color) { language = _language } fun speak()=println("Speak! $language") }
다형성
오버로딩: 동일한 클래스 안에서 같은 이름의 메서드가 매개변수만 달리해서 여러 번 정의될 수 있음
1 2 3 4 5 6
class Calc{ fun add(x: Int, y: Int): Int = x+y fun add(x: Double, y: Double): Double = x+y fun add(x: Int, y: Int, z: Int): Int = x+y+z fun add(x: String, y: String): String = x+y }
오버라이딩
- 하위의 새로운 메서드는 상위 클래스의 메서드 내용을 완전히 새로 만들어 다른 기능을 하게끔 정의
- 이때는 클래스 뿐만 아니라 상위 함수에도 open 키워드를 사용해야 함
1 2 3 4 5 6 7 8 9 10 11 12 13 14
open class Bird(var name: String, var wing: Int, var beak: String, var color: String){ fun fly() = println("Fly wing: $wing") open fun sing(vol: Int) = println("Sing vol: $vol") } class Parrot(name: String, wing: Int = 2, beak: String, color: String, var language: String = "natural") : Bird(name, wing, beak, color) { fun speak() = println("Speak! $language") final override fun sing(vol: Int){ println("I'm a parrot! The volume level is $vol") speak() } }
05-4 super와 this의 참조
| super: 상위 클래스 | this: 현재 클래스 |
|---|---|
| super.프로퍼티 이름 | this.프로퍼티 이름 |
| super.메서드 이름() | this.메서드 이름 |
| super() | this() |
super로 상위 객체 참조하기
this로 현재 객체 참조하기
여러 개의 부 생성자에서 참조하기
→ 부 생성자에 this가 있으면, 매개변수에 해당하는 다른 부 생성자를 참조하여 먼저 실행
주 생성자와 부 생성자 함께 사용하기
→ 부 생성자에 this가 있지만, 매개변수에 해당하는 다른 부 생성자가 없다면
→ 주 생성자를 참조하면 됨
바깥 클래스 호출하기
상위 클래스(Base)가 존재하고,
하위 클래스(Child) 안에 이너 클래스(Inside)가 존재할 경우의 참조 방식
- 이너 클래스에서 이너 클래스 접근: f( )
- 이너 클래스에서 하위 클래스 접근: Child( ).f( )
- 이너 클래스에서 상위 클래스 접근: super@Child.f( )
이너 클래스는 inner 키워드 붙여야 함
인터페이스에서 참조하기
인터페이스와 다른 클래스의 메서드 이름이 동일할 때, 함수 호출 방법
- super<A>.f(): A 클래스의 f()
- super<B>.f(): B 인터페이스의 f( )
05-5 정보 은닉 캡슐화
캡슐화: 클래스를 작성할 때 숨겨야 하는 속성이나 기능이 필요할 때
- 가시성 지시자
- 가시성: 각 클래스나 메서드, 프로퍼티의 접근 범위
- private: 이 요소는 외부에서 접근할 수 없음
- public: 이 요소는 어디서든 접근이 가능(default)
- protected: 외부에서 접근할 수 없으나 하위 상속 요소에서는 가능
- internal: 같은 정의의 모듈 내부에서는 접근이 가능
- 가시성 지시자와 클래스의 관계
- 클래스에서의 가시성 지시자에 따라 공개되는 접근 범위가 달라짐
- UML의 가시성 표기 기호
- -: privete
- +: public
- #: protected
- ~: package
05-6 클래스와 클래스의 관계
연관 관계, 의존 관계, 집합 관계, 구성 관계
- 연관 관계: 2개의 서로 분리된 클래스가 연결을 가지는 것
- 의존 관계: 한 클래스가 다른 클래스에 의존되어 있어 영향을 주는 경우
- 집합 관계: 연관 관계와 비슷하지만, 한 클래스가 다른 객체들을 소유할 수 있는 경우
- 구성 관계
- 집합 관계와 거의 동일하지만,
- 특정 클래스가 어느 한 클래스 내에 객체로 들어가는 것
- 객체 간 메시지 전달하기
- UML의 시퀀스 다이어그램으로 표현