GDSC HUFS 3기/Android with Kotlin Team 2

[2팀] Kotlin Section 7 - OOP(2)

NakyungIm 2021. 10. 4. 21:42

이 글은 udemy 강의 Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린을 참고하여 작성하였습니다.

- 작성자 : 임나경

- 개발환경은 Windows, Android Studio입니다.

 

 


 

 

1. Public, Private, Protected and Internal Examples (접근 제한자)


위와 같은 것들을 접근 제한자라고 한다.

접근 제한자(visibility modifier)란 클래스의 멤버를 외부의 어느 범위까지 이용하게 할 것인지를 결정하는 키워드이다.

코틀린에서는 변수나 함수를 클래스로 묶지 않고 소스파일의 최상위에 선언할 수 있고, 이 또한 접근 제한자로 범위를 제한할 수 있다.

 

접근제한자 최상위에서 이용 클래스 멤버에서 이용
public 모든 파일에서 가능 모든 클래스에서 가능
internal 같은 모듈 내에서 가능 같은 모듈 내에서 가능
protected X 상속 관계의 하위 클래스에서만 가능
private 파일 내부에서만 이용 클래스 내부에서만 이용
  • public : 접근제한없음. 접근 제한자 생략 시 자동으로 public
  • internal : 같은 모듈 내 접근. (모듈 = Gradle같은 빌드 도구에서 프로젝트 or 같은 세트 단위)
  • protected : 클래스 내부에서만 선언 가능
  • private : 내부로만 제한

 

 

 

2. Kotlin Constructors (생성자)


  • 클래스의 멤버 : 생성자, 변수, 함수, 클래스
  • 생성자 : 주 생성자, 보조 생성자로 나뉨

 

✅ 주 생성자

  • 주 생성자 선언
    // 주 생성자 선언
    class User constructor() {
    }
    
    // constructor 키워드 생략 가능
    class User() {
    }
    
    // 주 생성자 생략 시 컴파일러가 매개변수가 없는 주 생성자 자동 추가
    class User {
    }
    
    // 주 생성자 매개변수
    class User(name: String, count: Int) {
    }

 

  • 생성자 호출
    객체 생성 시 매개변수의 타입과 개수에 맞는 인자 전달!
    val user = User("nkim", 10)​

 

  • init 영역
    • 생성자에는 { }를 추가할 수 없다. 이 때 init을 이용해 주 생성자의 본문을 구현할 수 있다.
    • init으로 지정한 영역은 객체 생성 시 자동 실행됨
    • 꼭 선언할 필요는 없음! 주 생성자의 본문을 구현하고 싶을 때 사용
    • 보조 생성자에서도 실행되지만 보조 생성자는 클래스 안에 선언하므로 { }를 이용해 본문 지정 가능.
      즉, init 영역은 주로 주 생성자 본문 구현 용도로 사용됨
    • 예제
      class User(name: String, count: Int){
          init {
              println("i am init!")
          }
      }
      
      fun main() {
          val user = User("nkim", 10)
      }​
    • 출력
      i am init!​

 

✅ 보조 생성자

  • 보조 생성자 선언
    class User {
        constructor(name: String){
        	println("1")
        }
        constructor(name: String, count: Int){
        	println("2")
        }
    }
    
    fun main() {
        val user1 = User("nkim")
        val user2 = User("nkim", 10)
    }​​
  • 출력
    1
    2​

 

✅ 보조생성자에 주생성자 연결 👉🏻 this() 이용

둘 중 하나만 할 경우에는 문제가 없다. 만약 보조/주 생성자 둘 다 선언 시 반드시 생성자끼리 연결해줘야함!

class User(name: String) {
    constructor(name: String, count: Int): this(name){
    	// 생략
    }
}

fun main() {
    val user = User("nkim", 10)
}​​
  • 보조 생성자 선언부에 this(name)을 추가하면, 보조 생성자로 객체 생성 시 주 생성자가 함께 호출됨
  • 주 생성자 있는 상태에서 보조 생성자 여러개 선언 시 this 모두 사용하기

 

✅ 주 생성자 VS 보조 생성자를 왜 구분하나요?

둘 중 뭘로 만들던 개발자 마음!!

공통된 코드는 주 생성자에. 나머지는 보조 생성자에~

 

 

 

3. Kotlin Inheritance (상속)


 상속과 생성자

  • 상속 : 클래스 선언 시 다른 클래스를 참조해서 선언하는 것. 기존 클래스 재사용 가능
  • 클래스 상속 형식
    open class Super { // open 키워드로 상속 가능하게 허용
    }
    class Sub: Super() { // Super을 상속받아 Sub 클래스 선언
    }
  • 상위 클래스 생성자 호출
    • 하위 클래스의 생성자는 상위 클래스의 생성자를 호출해야함
    • 매개변수 없는 상위 클래스 상속
      • class Sub: Super() { } 에서 Super()은 Super 클래스를 상속받음 + 이 클래스의 매개변수가 없는 생성자 호출
    • 매개변수 있는 상위 클래스 상속
      • 매개변수 구성에 맞게 인자 전달
      • open class Super(name: String) {
        }
        class Sub(name: String): Super(name) {
        }

 

 Overriding (재정의)

  • 상위 클래스에 정의된 멤버(함수, 변수)를 하위 클래스에서 재정의
  • 즉, 상위 클래스에 선언된 변수나 함수를 같은 이름으로 하위 클래스에서 다시 선언
  • 주로 함수 재정의에 사용
  • 같은 함수명으로 하위 클래스에서 새로운 로직을 추가하고 싶을 때 사용
  • 규칙
    • 상위 클래스 : overriding 허용할 변수나 함수 선언 앞에 open 키워드 추가
    • 하위 클래스 : 재정의 할 변수나 함수 선언 앞에 override 키워드 추가

 

 

 

4. Kotlin Polymorphism and Abstraction (다형성과 추상화)


 다형성

  • 이름은 같지만 매개변수가 다르거나, 다른 동작을 하도록 하는 것
  • 이해하기 쉽고 변경하기 쉬운 코드 작성 가능

 

 Overloading VS Overriding

 

[Kotlin] 클래스 5 — 다형성(polymorphism)

Kotlin 언어로 overloading과 overriding 그리고 binding 개념을 거쳐 다형성에 대한 개념을 다룹니다.

medium.com

 

 추상 클래스

  • 아직 구현되지 않고 선언만 된 추상 메서드를 가지고 있는 클래스
  • 추상 클래스는 메서드가 구현되지 않아서 이 클래스를 직접 객체로 만들 수 없고 반드시 상속을 받는 자식 클래스가 있어야함
  • 추상 메서드는 서브클래스에서 반드시 override 해서 사용
  • abstract 키워드 사용 시 클래스나 함수에 open 키워드 따로 명시하지 않아도 됨
  • 다중 상속 불가
  • 인터페이스와 클래스의 중간
  • 추상 클래스는 객체 생성 불가, 생성자 가질 수 있음
  • 추상 클래스 정의
    fun main(args : Array<String>) {
        var tempClass : AbstractClass = SubClass()
        tempClass.generalMethod()
        tempClass.abstractMethod()
    }
     
    open abstract class AbstractClass {
        //자식 클래스에서 그냥 사용할 수 있는 일반 메서드
        fun generalMethod () {
            println("일반 메서드")
        }
     
        //자식 클래스에서 오버라이딩 해야 사용할수 있는 추상 메서드
        open abstract fun abstractMethod()
    }
     
    class SubClass : AbstractClass() {
        override fun abstractMethod() {
            println("추상 메서드 구현")
        }
    }​
  • 결과
    일반 메서드
    추상 메서드 구현​

 

 

 

첫 포스팅 완료~~ GDSC 흥해라~~💙