언어가 지향하고 있는 패러다임을 배우는 것도 중요하다.
객체지향 프로그래밍에서 중요한 세 가지
클래스, 상속, 인터페이스
개인적으로 인터페이스는 정말 활용하기 좋은 것 같다.
잘 쓰면 정말 유용하기에 자알 써보고 싶다..ㅎㅎ
인터페이스 Interface
인터페이스는 추상 메소드를 포함할 수 있는 참조 타입으로, 인터페이스 자체로는 객체를 생성할 수 없지만, 다른 클래스가 인터페이스를 구현(Implement)함으로써 메소드의 실제 구현을 제공할 수 있다.
- 규약(프로토콜)
- 인터페이스에 비어 있는 것을 채워주면 해당 인터페이스로 봐주겠다.
- == abstract를 구현하면 해당 Type으로 봐주겠다.
인터페이스를 보고 구현된 클래스의 객체와 의사소통할 수 있다.
- 의사소통 -> 사용할 수 있다.
- 이것을 가능하게 만든 규칙이 규약이다.
더 자세한 정보를 알고 싶다면 아래의 공식 사이트에서 예제와 설명을 참고하면 좋을 것 같다.
https://kotlinlang.org/docs/interfaces.html#interfaces-inheritance
Interfaces | Kotlin
kotlinlang.org
(예제) 인터페이스 정의하기 : ElectronicDevice
자, 이제 예시를 보자. '전자기기'를 제어하는 시스템을 구현해보겠다.
이 시스템은 다양한 전자기기(예:TV, 에어컨, 라디오 등)를 켜고 끄는 기능을 통일된 방식으로 제어할 수 있다.
interface ElectronicDevice {
fun turnOn()
fun turnOff()
}
(예제) 인터페이스를 사용하여 각 클래스 구현
구현은 간단하다. 정의했던 메소드를 override 해주면 된다. 새로운 기능을 추가해도 된다.
- 안드로이드 스튜디오에서는 구현할 메소드를 자동 생성해주는 기능도 있다.
> 인터페이스를 적용할 클래스 좌클릭 > Generate > Inplement Members >
class AirConditioner : ElectronicDevice {
override fun turnOn() {
println("Air Conditioner is now on, cooling down.")
}
override fun turnOff() {
println("Air Conditioner is now off.")
}
}
class Radio : ElectronicDevice {
override fun turnOn() {
println("Radio is playing music now.")
}
override fun turnOff() {
println("Radio has been turned off.")
}
}
예시에서 인터페이스는 전자기기의 상태 변경을 표준화하는 역할을 한다.
ElectronicDevice 인터페이스를 구현함으로써 다양한 기기에 대해 동일한 방법으로 기기를 켜고 끌 수 있으며, 코드의 유연성과 확장성을 보장한다.
🤔 궁금해요!
배우다 보니 인터페이스에 대해 더 궁금해져서 GPT에 물어봤다.
왜 인터페이스에서는 open 키워드를 사용하지 않을까?
- 코틀린에서 인터페이스의 멤버들은 기본적으로 'abstract'로 간주됨
인터페이스 내의 메소드나 속성이 구현이 되어있지 않음 → 인터페이스의 멤버는 이미 재정의 가능한 상태이기 때문
인터페이스를 미리 정의할 수 있을까?
(1) 인터페이스에서 속성 정의하기
- 백킹 필드(backing field)를 사용할 수 없다.(상태를 저장 못함)
- 하지만, 속성에 대한 접근자(getter, setter)를 정의할 수 있음
interface Vehicle { val numberOfWheels: Int // abstract val hasMotor: Boolean get() = true fun start() fun stop() } class Bicycle : Vehicle { override val numberOfWheels = 2 }
(2) 인터페이스에서 메소드 정의하기
- 구현시에는 override를 하지 않아도 된다.
- 'final override'로 구현하면 구현될 클래스에서 override를 금지한다.
interface Vehicle { val numberOfWheels: Int val hasElectronMotor: Boolean fun start() { // default method println("let's go.") } fun stop() } class ElectricCar : Vehicle { override val numberOfWheels = 4 override val hasElectronMotor = true // default can be override override fun start() { println("Electric car is starting with silent mode.") } }
인터페이스에서는 다중 구현이 가능할까?
- 다중 상속을 통해 여러 부모로부터 기능을 상속받아 더 풍부한 구현 가능
- 코드의 재사용성을 높이고, 유지 보수를 쉽게 하며, 시스템 확장성 향상
- 속도 조절, 방향 조절을 할 수 있는 자동차 인터페이스 다중 구현 예시)
interface SpeedControl { fun accelerate() fun decelerate() } interface DirectionControl { fun turnLeft() fun turnRight() } class Car : SpeedControl, DirectionControl { override fun accelerate() { println("차량 속도 증가") } override fun decelerate() { println("차량 속도 감소") } override fun turnLeft() { println("차량 좌회전") } override fun turnRight() { println("차량 우회전") } }
인터페스에서 다중 상속 문제인 다이아몬드 문제가 생길 수 있나요?
다이아몬드 문제는 하나의 클래스가 두 개 이상의 클래스로부터 상속받을 때, 같은 메소드나 속성을 두 부모 클래스 모두에서 상속받아 충돌이 발생하는 문제이다.
→ 이는 클래스가 두 부모의 구현을 어떻게 상속받을지 결정하기 어려워서 발생한다.
아래의 방법으로 인터페이스의 타입을 명시하는 방법으로 해결할 수 있다.interface A { fun display() { println("Display from A") } } interface B { fun display() { println("Display from B") } } class C : A, B { override fun display() { super<A>.display() super<B>.display() } } fun main() { val c = C() c.display() // Display from A"와 "Display from B" 둘 다 출력됨 }
정리해보자.
- 인터페이스
코틀린의 인터페이스는 클래스 간에 메소드를 공유하는 계약(프로토콜)으로, 구현 클래스에 구체적인 행동을 지정한다.
이는 클래스가 인터페이스를 구현하면, 해당 인터페이스의 모든 추상 메소드를 오버라이드해야 한다는 것을 의미한다. - 디폴트 메소드와 추상 속성
: 인터페이스는 디폴트 메소드를 제공할 수 있어, 인터페이스를 수정할 때 기존 구현에 영향을 미치지 않는 확장이 가능하다. - 다중 구현과 다이아몬드 문제 해결
코틀린 인터페이스는 다중 구현을 지원하여 하나의 클래스가 여러 인터페이스를 구현할 수 있다. 또한, 다중 구현에서 발생할 수 있는 다이아몬드 문제를 super<Type> 구문을 사용하여 명시적으로 어떤 인터페이스의 메소드를 호출할지 지정함으로써 해결한다. - 확장성 및 유지보수
인터페이스를 사용하면 시스템의 확장성과 유지보수성이 향상된다. 새로운 기능을 추가하거나 기존 기능을 변경할 때, 인터페이스를 통해 손쉽게 적용할 수 있으며, 코드의 일관성을 유지할 수 있다.
'2024 활동 > Kotlin·Android' 카테고리의 다른 글
[Android] Intent로 ImageView 전달하기 (0) | 2024.05.28 |
---|---|
[Android Studio] 빌드 오류 해결 intent-filter (0) | 2024.05.08 |
[Kotlin] 클래스 심화 : 상속, 오버라이딩, 형변환, 스마트 캐스트 (0) | 2024.04.18 |
[Kotlin] Null Safety 예제로 쉽게 이해하자! (0) | 2024.04.18 |
[Kotlin] Backing Field가 뭔가요? (1) | 2024.04.12 |