상속은 한 클래스가 다른 클래스의 속성과 매소드를 물려받는 것
코드 재사용과 확장에 용이하다.
코틀린에서 상속을 사용하기 위해선 부모가 될 클래스에 open 키워드를 붙여줘야함
오버로딩 vs 오버라이딩
오버로딩 : 매소드의 이름은 같지만 매개변수의 타입이나 갯수가 다른것
오버라이딩 : 자식 클래스에서 상속받은 부모의 매소드를 재정의 하는것
fun main() {
val obj1 = BaseClass()
obj1.coreValue()
val obj2 = Secondary()
obj2.coreValue()
}
open class BaseClass {
//다른 class들이 상속 받을 클래스
//open 키워드를 써서 class를 상속 할 수 있는 상태로 만든다
fun coreValue() {
println("베이스 클래스")
}
}
class Secondary : BaseClass() {
}
Secondary class엔 아무것도 없지만 BaseClass()를 상속받았기때문에 coreValue() 함수 호출 가능
오버라이딩 : 상속 관계에서 부모의 함수를 자식 클래스에서 재정의
-> 코틀린에서 함수를 오버라이딩 할 수있도록 하려면 함수에도 open키워드를 써줘야 한다
super : 오버라이딩한 함수를 실행할 때 부모에서 정의한 내용을 먼저 실행하란뜻
fun main() {
val obj1 = BaseClass()
obj1.coreValue()
val obj2 = Secondary()
obj2.coreValue()
obj2.role()
}
open class BaseClass {
//다른 class들이 상속 받을 클래스
//open 키워드를 써서 class를 상속 할 수 있는 상태로 만든다
fun coreValue() {
println("베이스 클래스")
}
open fun role() { //오버라이딩 할 수 있도록 하려면 얘도 open으로 열어줘야함
println("킹")
}
}
class Secondary : BaseClass() {
override fun role() {
super.role() //super : 기본적으로 BaseClass에서 정의한 내용을 실행하란뜻
print("세자 입니다")
}
}
참고
super 함수를 닫으면 당연히 부모에서 정의함 role 안나옴
super는 부모의 함수를 부르는 것이기 떄문
class Secondary : BaseClass() {
override fun role() {
//super.role() //super : 기본적으로 BaseClass에서 정의한 내용을 실행하란뜻
print("세자 입니다")
}
}
함수나 속성을 사용하겠다는 뜻
인터페이스는 open 키워드를 사용할 필요가 없이 상속이 가능하다
인터페이스를 구현하려면 함수를 구현하고 오버라이딩해야한다
interface Archery {
fun archery() {
println("아아아")
}
}
interface Singer {
fun sing() {
println("가수")
}
}
class Offspring : Secondary(), Archery, Singer {
override fun archery() {
super.archery()
}
override fun sing() {
super.sing()
}
override fun role() {
super.role()
}
}
fun main() {
val obj4 = Offspring()
obj4.role()
obj4.archery()
obj4.sing()
}
왜? 인터페이스를 사용해야할까?
추상화
인터페이스는 클래스가 구현할수 있는 계약을 정의할 수 있게 하는데 이 계약을 파생 클래스가 반드시 구현해야하는 메소드로 구성되어있으며 무엇을 어떻게 할지 추상화함, 어떻게 할지는 지금 당장 정하지 않으면서 클래스가 특정 기능을 갖게 할 수 있다
다중상속
객체지향 언어는 단일 상속만 가능한데 이러한 한계를 극복하기 위해 인터페이스를 사용하면 다중 상속이 가능하다
유연성과 호환성
다양한 방법으로 같은 인터페이스를 구현한 여러 클래스를 만들수 있다
그 클래스들의 객체는 연관된 인터페이스에 의해 가능성이 보장된다면 콘텍스트에서 상호 교환적으로 사용할 수 있다
캡슐화
클래스 내부 구현 사항을 숨길 수 있어 인터페이스에서 선언한 매소드만 노출할 수 있다
확장성
소프트웨어가 커지면 인터페이스는 인터페이스에 따른 클래스에 영향을 주지 않고도 기본이 되는 규현을 확장하고 리팩토링 할 수 있다