[코틀린 기초] 클래스와 상속, 오버라이딩, 추상 클래스, 인터페이스, 코틀린 기본 프로젝트 구조, 스코프와 접근 제한자
lesson 10 클래스의 상속
open: 이 키워드가 붙은 클래스가 부모 클래스가 될 수 있도록 클래스 선언시 붙여줄 수 있는 키워드
규칙
1. 서브 클래스는 슈퍼클래스에 존재하는 속성과 '같은 이름'의 속성을 가질 수 없다.
2. 서브 클래스가 호출될 때는 슈퍼 클래스의 생성자까지 호출되어야 함
예제코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
fun main() {
var cat = Animal("애쉬", 2, "고양이")
var dog1 = Animal("둥이", 3, "개")
var dog2 = dog("구찌", 3)
cat.introduce()
dog1.introduce()
dog2.introduce()
// var dog3 : dog
// dog3 = dog1 <= 이렇게 downcasting 안되네
// dog3.bark()
dog2.bark()
}
open class Animal( var name : String, val age : Int, var type : String){
init{
println("Animal 생성됨 !")
}
fun introduce(){
println("안녕하세요, 저는 ${type}이고 나이는 ${age} 이름은 ${name}입니다.")
}
}
class dog (name : String, age : Int) : Animal(name, age, "개"){
init{
println("개가 생성됨 !")
}
fun bark(){
println("멍멍 !")
}
}
|
cs |
27행: : Animal(name, age, "개") 파라미터에 클래스의 속성으로 만들어주는 var를 붙이지 말고 일반 파라미터로 받도록 하자.
서브 클래스의 생성자 뒤에 : 콜론을 붙이고 슈퍼 클래스의 생성자를 호출하여 상속 !!
lesson 11 오버라이딩과 추상화
슈퍼 클래스의 메소드를 오버라이딩 하기 위해서는 슈퍼클래스의 메소드 선언부 앞에 open 키워드로 명시해줘야 한다. open이 없으면 오버라이딩 할 수 없다.
그리고 서브 클래스의 오버라이딩 메소드 선언부에서 앞에 override 키워드를 붙여줘서 명시해주자 !
오버라이딩 !
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
fun main() {
var cat = Animal("애쉬", 2, "고양이")
var dog1 = Animal("둥이", 3, "개")
var dog2 = dog("구찌", 3)
cat.introduce()
dog1.introduce()
dog2.introduce()
// var dog3 : dog
// dog3 = dog1 <= 이렇게 downcasting 안되네
// dog3.bark()
dog2.bark()
}
open class Animal( var name : String, val age : Int, var type : String){
init{
println("Animal 생성됨 !")
}
open fun introduce(){
println("안녕하세요, 저는 ${type}이고 나이는 ${age} 이름은 ${name}입니다.")
}
}
class dog (name : String, age : Int) : Animal(name, age, "개"){
init{
println("개가 생성됨 !")
}
fun bark(){
println("멍멍 !")
}
override fun introduce(){
println("안녕하세요, 저는 개입니다 왈왈 ! 이름은 ${name}입니다.")
}
}
|
cs |
22행: open fun introduce() <- 함수 앞에 open 붙은걸 확인
35행: override fun introduce() <- 함수앞에 override 붙은 거 확인
추상 클래스와 추상함수 만들기
abstract를 클래스 선언부와 메소드 선언부 각각 앞에 붙이면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
fun main(){
var a = rabbit()
a.sniff()
a.eat()
}
abstract class animal(){
abstract fun eat()
fun sniff(){
println("킁킁")
}
}
class rabbit : animal(){
override fun eat(){
println("당근을 먹습니다.")
}
}
|
cs |
비교적 간단해서 넘어가자 !
인터페이스
java의 인터페이스는 추상화 함수로만 이루어져 있는 순수 추상화 기능을 하는 것으로 알려져 있다.
but!! kotlin의 인터페이스는 속성, 추상함수, 일반함수 모두를 가질 수 있다 !
(생성자는 가질 수 없는 것은 java와 동일.)
따로 abstract나 open 키워드가 없어도 ..
구현부가 있는 함수 -> open 함수로 간주 (서브 클래스에서 override 가능)
구현부가 없는 함수 -> abstract 함수로 간주 (서브 클래스에서 override 가능)
java와 마찬가지로 한 개의 클래스는 한 번에 여러개의 인터페이스를 상속 받을 수 있다.
코드예제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
fun main(){
var a = Dog()
a.eat()
a.run()
}
interface Runner{
fun run()
}
interface Eater{
fun eat(){
println("음식을 먹습니다.")
}
}
class Dog : Runner, Eater{
override fun run(){
println("우다다다 뛰어가자!")
}
override fun eat(){
println("허겁지겁 먹습니다.")
}
}
|
cs |
인터페이스는 선언시 인터페이스명( ) <- 이 소괄호가 생략된다. 생성자가 없어도 되는 것이다. 따라서 인터페이스를 상속 할 때도 콜롬 : 뒤에 소괄호 없이 인터페이스 명만 적어주면 된다. 여러개의 인터페이스를 상속 할 때는 , 쉼표로 구분한다.
신기한 것은 21~23행을 지워버려도 실행된 다는 것이다. 이미 인터페이스 Eater에서 (12행) eat가 이미 구현되어져 있고, open이 없어도 open 기능을 하기 때문이다.
lesson 12 기본 프로젝트 구조
프로젝트: 코틀린으로 어플리케이션 짤 때 관련한 모든 내용을 담는 큰 틀
모듈: 하나의 프로젝트는 다수의 모듈로 이루어진다. 직접 만들수도, 라이브러리 모듈을 가져올 수도 있다.
모듈안에는 다수의 폴더와 파일이 존재할 수 있다. 리소스 파일 등도 포함.
- 프로젝트, 모듈, 폴더 및 파일이 실제 파일 시스템에 기반한 물리적인 구조라면
논리적인구조로는 패키지가 있다. 개발시에 소스코드의 소속을 지정하기 위한 논리적 단위.
- 패키지명은 보통 개발한 회사의 도메인을 거꾸로한 다음 기능과 세분화에 따라 . 와 함게 연장한다.
ex) youtube.com => com.youtube => com.youtube.패키지기능.기능별세분화
- 다른 패키지의 멤버를 사용하고 싶다면 import 다른패키지명 <- 이런식으로 import해서 사용해야한다.
- 코틀린은 자바와 다르게 클래스명과 파일명이 일치하지 않아도 되며,하나의 파일에 여러개의 클래스를 넣어도 알아서 컴파일 가능. => 왜냐하면 파일이나 폴더를 기준으로 구분하지 않고 파일내에 있는 package 키워드를 기준으로 구분하기 때문이다. 마찬가지로 package도 폴더구조와 package명을 일치시키지 않아도 된다. 단순히 package 키워드로 명시만 해주면 컴파일러가 알아서함.
lesson 13 변수, 함수, 클래스의 접근 범위와 접근 제한자
스코프 = 범위 = 공유하는 정도 = 공용 범위를 제어하는 단위
규칙
1. 스코프 외부에서는 스코프 내부의 멤버를 참조 연산자로만 참조가 가능하다.
ex) 클래스의 맴버를 참조할 때 a.eat() a라는 인스턴스명을 앞에 붙여서 참조
ex) import 패키지명
2. 동일 스코프 내에서는 멤버들을 공유할 수 있다.
당연한 것
3.하위 스코프에서는 상위 스코프의 멤버를 재정의 할 수 있습니다.
당연한 것. ex) C언어에서 전역변수로 선언한 int a = 100; 을 for문이나 다른 location안에서 int a = 200 으로 다시 재정의하고 사용할 수 있다. 이때 두 a는 모두 다른 a이다.
접근제한자: 스코프 외부 -> 내부로 접근 할 때 개발자가 접근정도를 제한하는 정도
패키지 스코프
public: 기본값 어떤패키지에서도 접근가능
internal: 같은 모듈 내에서만 접근가능
private: 같은 파일 내에서만 접근가능
protected: x
클래스 스코프
public: 기본값 클래스 외부에서 늘 접근 가능
internal: x
private: 클래스 내부에서만 접근 가능
protected: 클래스 자신과 상속받은 클래스에서 접근가능
학습 출처:
테크과학! DiMo-디모의 Kotlin 강좌 (9~13)
(www.youtube.com/playlist?list=PLQdnHjXZyYadiw5aV3p6DwUdXV2bZuhlN)
구독과 좋아요 !
+추가 공부
open class A {
open fun f() = println("A Class f()")
fun a() = println("A Class a()")
}
interface B {
fun f() = println("B Interface f()")
fun b() = println("B Interface b()")
}
class C : A(), B {
override fun f() {
println("C Class f()")
}
fun test(){
f()
b()
super<A>.f()
super<B>.f()
}
}
fun main() {
val c = C()
c.test()
}
상속받는 super클래스가 여러개인데 슈퍼클래스들의 함수중 함수이름이 동일한 경우가 있는경우. 슈퍼클래스의 함수원형을 그대로 사용하고 싶다면,
super<A>.f()
super<B>.f()
이렇게 <>에 슈퍼클래스의 이름을 명시해줘서 사용한다.