이 글은 유데미 강의 Android 12 및 Kotlin 개발 완전 정복를 참고하여 작성하였습니다.
작성자 : 나영수
개발환경은 Windows, Android Studio입니다.
-상속
* 서브클래스(=자식 클래스= 파생 클래스), 슈퍼클래스(=부모 클래스=기본 클래스)로 크게 나뉜다.
* open class만이 상속이 가능하다.
fun main() {
var a = Animal("흰둥이", 5, "개") //a변수는 Animal 객체 변수
var b = Dog("흰둥이", 5) //b변수는 Dog 객체 변수(Dog는 Animal을 상속받음)
a.introduce() //Animal class 내의 내장 함수
b.introduce() //Dog class 내의 내장 함수가 아니지만 Animal을 상속 받았으므로 사용 가능
b.bark() //Dog class 내의 내장 함수
var c = Cat("루이", 1) //c변수는 Cat 객체 변수
c.introduce()
c.meow()
}
//코틀린은 default가 상속금지(java의 경우 아무것도 선언하지 않으면 상속가능) -> open 사용해야함.
open class Animal(var name: String, var age: Int, var type: String) {
fun introduce() {
println("저는 ${this.type} ${this.name}이고 ${this.age}살 입니다.")
//해당 클래스 내의 변수를 선언할때는 생성자인 this를 사용한다.(사실 여기서는 사용안해도 무방)
}
}
//var, val 등으로 붙이면 속성으로 선언되기 때문에 안됨
class Dog(name: String, age: Int) : Animal(name, age, "개") {
//interface와는 다르게 상속에서는 여러가지 기능을 확장시킬 수 있다.
fun bark() {
println("멍멍")
}
}
class Cat(name: String, age: Int) : Animal(name, age, "고양이") {
fun meow() {
println("야옹 야옹")
}
}
- 다형성
다형성이란 비슷한 특성을 가진 객체들이 공통된 방법으로 여겨지는 것이다.
(하나의 객체가 여러 가지 타입을 가질 수 있는 것을 의미)
-> 결론적으로 봤을때 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 한 것
ex ) Parent class 와 Child class가 있다고 가정해보자.
class Parent{}
class Child extends Parent{}
Parent cp = new Child(); //가능
Parent ch = new Parent(); //가능
Child ck = new Child(); //가능
위의 3가지 경우는 모두 성립가능한 객체선언이다.
(이 3가지의 경우만 보더라도 하나의 객체가 여러 타입을 가질 수 있다.) -> child 타입, parent 타입
Child cl = new Parent(); //불가능
하지만 위의 경우 자식 클래스 타입의 참조 변수로는 부모 클래스 타입의 인스턴스를 참조할 수 없다.
단순히 말하면 부모는 자식의 인스턴스를 참조할 수 있지만 자식은 부모의 인스턴스를 참조할 수 없다.
(약간 상속하고 반대되는 느낌으로 이해하면 괜찮을 것 같다. 상속의 경우 자식이 부모의 모든 것을
쓸수 있지만 자식에서 수정한 것을 부모가 알 수 없는 것과 반대로 다형성은 부모는 자식을 알지만
자식은 부모를 모르기 때문이다.)
- 인터페이스
인터페이스는 다른 인터페이스에 상속받을 수 있다.
그리고 인터페이스는 클래스들의 기능을 확장해준다는 점에서 의의를 갖는다.
그리고 일단 함수와 프로퍼티를 바로 구현하지 않고 선언만 하고 싶을 때 사용하기 좋다.
인터페이스 내부에서는 명세만 할 뿐이지 바디는 갖지 않는다. 즉 객체를 만들지 못한다.
- 추상 클래스(abstract class)
추상메소드를 가진 클래스는 무조건 추상클래스가 되어야 한다.
--추상클래스와 인터페이스 공통점? --
추상클래스와 인터페이스는 상속받는 클래스 혹은 구현하는 인터페이스 안에 있는 추상 메소드를 구현하도록 강제한다. 인스턴스화가 불가능하다.
--추상클래스와 인터페이스 차이점?--
가장 큰 차이점은 추상클래스와 인터페이스가 갖는 목적성이다. 그리고 다중상속의 유무가 가장 큰 차이점이다.
상속 : 상속은 슈퍼클래스의 기능을 이용하거나 확장하기 위해서 사용되므로 다중 상속의 모호성 때문에 하나만 상속받을 수 있다.(만약 상속하는 두 곳에서 동일한 메소드가 있다면 그 메소드를 확장 시킬때 어떤 메소드를 확장시키는지 모호해진다.)
인터페이스: 하지만 인터페이스를 구현한 객체들은 동일한 동작을 약속하기 위해 존재하므로 다중 상속되어도 상관없다.(그냥 상속받는 class들의 함수를 다 쓰기만 하면 됨)
--둘중 하나만 있게되면 생기는 번거러움--
만약 모든 클래스가 인터페이스만 통해서 기본틀을 구성하면 공통으로 필요한 기능들도 모든 클래스에서 오버라이딩해서 다시 재정의 해야 하는 번거로움이 생긴다. 이렇게 공통된 기능이 필요한곳은 추상클래스를 이용해서 자식 클래스에서 사용할 수 있도록 하면 된다.(추상클래스에서는 필요한 메서드를 모두 정의해놓기 때문에 가져다 쓰기만 하면 되지만 인터페이스의 경우는 모두 다시 선언해야한다.)
그럼 모든 클래스를 추상클래스만 이용한다면? 이라는 생각을 할 수 있지만 차이점에서 설명했듯이 클래스는 다중상속이 제한되기 때문에 각각 다른 추상클래스를 상속해야하는데 공통된 기능이 필요하다면 인터페이스를 이용하는 것이 효율적이다.
https://myjamong.tistory.com/150
[JAVA] 추상클래스 VS 인터페이스 왜 사용할까? 차이점, 예제로 확인 :: 마이자몽
추상클래스 인터페이스 왜... 사용할까? 우리는 추상클래스와 인터페이스에 대해서 알고 있냐고 누가 물어본다면 알고 있다고 대답을 하고있습니다. 그런데 이론적인 내용 말고 정작 "왜 사용하
myjamong.tistory.com
-형 변환
//<unsafe 캐스팅>
val obj1: Any = "I have a dream"
val str1: String = obj1 as String
println(str1.length)
//obj1이 String이므로 캐스팅이 성공하고 길이가 출력된다.(obj1이 Any -> String)
//단 obj1이 null일 경우 ?가 없어서 null exception에서 자유롭지 않아서 unsafe 캐스팅이다.
//<safe 캐스팅>
val obj3: Any = 1337
val str3: String? = obj3 as? String //이렇게 되면 obj3가 null일 경우에도 정상적으로 작동 가능하다.
println(str3)
'GDSC HUFS 4기 > Kotlin Team #7' 카테고리의 다른 글
[7팀] 계산기 -xml 사용법과 UI 생성 배우기 part 2 (0) | 2022.10.31 |
---|---|
[7팀] 계산기 - XML 사용법과 UI 생성법 배우기 - 안드로이드12 (0) | 2022.10.31 |
[7팀]코틀린 기초 더 배우기(2) (0) | 2022.10.11 |
[7팀]코틀린 기초 더 배우기(1) (0) | 2022.10.10 |
[7팀] 코틀린 객체 지향 프로그램 기초(1) (0) | 2022.10.07 |