Kotlin - OOP

Hue·2023년 3월 21일
0

Android/Kotlin

목록 보기
39/42

객체지향 (Obbject Oreinted Program)

① class, 객체

객체 생성 - new 키워드 없음
별도의 파일로 클래스 설계 가능함

멤버변수 property : 반드시 초기화 필요
(cf. 자바에서는 '0에 해당하는 값'으로 자동초기화)
멤버함수 method

② 생성자

②-1. primary constructor : 주생성자
클래스 이름 옆에 작성(construictor 생략하고 ()만 작성가능), 주생성자는 별도의 {}없음
--> 주생성자가 호출될때 같이 호출되는 초기화 블럭이 있음 : init{} (이곳에 주생성자의 내용작성)

생성자의 매개변수는 메소드에서 사용할 수 없음
(ex. 자바로 작성하는 Adapter에서도 생성자로 받은 Context를 다른 지역의 메소드에서 사용하기 위해 멤버변수를 만들어서 사용)
--> 주생성자의 파라미터에 변수 키워드 (var/val)가 있으면 파라미터면서 멤버변수
추가 작업없이 메소드에서 바로 사용이 가능해짐

애초에 클래스이름 옆에 파라미터를 받으면서 작성하기때문에 오버로딩 불가

🧐 overloading vs overriding

⁕ overloading : 메소드의 이름은 같지만 파라미터가 다른 경우
⁕ overriding : 상위 클래스의 메소드를 하위 클래스에서 재정의하는 경우

②-2. secondary constructor : 보조생성자
자바와 유사한 형태로, 클래스 안에 메소드처럼 존재하는 생성자

클래스 안에 따로 작성하기때문에 파라미터를 다르게 받을 수 있으므로 오버로딩 가능
주생성자처럼 변수 키워드를 붙여 멤버변수와 파라미터를 동시에 받는 작업은 불가능

주생성자와 함께 사용할때는 반드시 보조생성자에서 주생성자의 호출문을 명시적으로 불러야함 - this()
(이때 보조생성자의 값만 나오는 것이 아니라 주생성자도 함께 출력됨)

class Simple constructor() {
    init {
        println("Simple primary constructor")
    }

    constructor(num:Int):this(){
        println("Simple overloading constructor")
    }
}

③ 상속

상속 문법 extends --> :
코틀린에서는 기본적으로 final, 만들자마자 상속이 불가 --> open 키워드가 있어야 함

  • 업캐스팅 (up casting) : 부모 클래스의 참조변수로 자식 클래스 참조
    (옛날 리모컨으로 최신 텔레비전 제어, 넷플릭스 안됨)
    부모와 자식 모두 같은 함수명의 메소드가 있어도 실제로 참조하는 객체의 메소드가 호출됨 - 다형성
var first:First = Second()
first.show() //Second()의 show()메소드
  • 다운캐스팅 (down casting) : 자식이 부모를 컨트롤 불가, 하지만 실질적으로 참조하고 있는 것은 자식 클래스가 맞으므로 형변환하여 참조 가능
var second:Second = first as Second

kotlin에서는 기본적으로 final, 만들자마자 상속 불가 --> 상속해줄 클래스 앞에 open 키워드 있어야 함

오버라이드의 경우 반드시 메소드 앞에 override 명시 (메소드의 오버라이드 기본적으로 불가 --> open 필요

⁕ 클래스 = 상속, 메소드 = 오버라이드

④ interface, 익명클래스

인터페이스는 객체 생성 불가
기능설계가 되어있지 않음
인터페이스의 추상메소드들을 구현하는 별도의 클래스를 설계 - 이 클래스를 객체로 만들어서 내부의 메소드 사용

기능없는 인터페이스/추상메소드 왜 사용할까?
모두 같은 이름을 사용하므로써 ✌규격을 정의✌할 수 있음, 이로써 운영체제에 대응하기도 수월해짐!

코틀린에서는 implement 키워드 대신 : 사용
인터페이스를 구현할때는 상속과 다르게 인터페이스명 옆에 생성자 호출문() 없음

interface Clickable {
	fun onClick()
} //인터페이스

class Test:Clickable{
    override fun onClick() {
        println("clicked!")
    }
} //인터페이스 implement 클래스

④-1. 익명클래스
위처럼 추상메소드를 사용하기위해 새로운 클래스를 명명하는것이 번거롭고 불편함
익명클래스 : 객체를 생성하면서 인터페이스를 그 자리에서 구현하는 이름없는 클래스를 이용
코틀린에서 익명클래스를 만드는 키워드 : object

var c:Clickable = obect:Clickable {
	override fun onClick() println("Clicked")
}

⑤ inner class

이너클래스는 외부에서 직접 객체 생성 불가
outer 없이 불러서 사용하지 못하도록
(ex. 다이얼로그의 내부 버튼인데 다이얼로그없이 사용하는 경우...)

코틀린에서는 클래스 내부에 있다고 무조건 이너클래스가 아님 : 클래스 앞에 inner 키워드 필요

이너클래스의 장점 : outer class의 멤버를 내것처럼 호출이 가능해짐

⑥ 동반객체 companion object

정적멤버 static 키워드의 대체 문법
클래스에 붙어있는 객체같은 느낌, 정적멤버처럼 별도의 객체생성없이 클래스명만으로 접근 가능

class Sample {
	var a:Int = 10 //인스턴스 변수는 객체 생성할때만 사용가능
    companion object {
    	var b:Int = 20
    }
}

println(Sample.b)
//컴패니언 오브젝트 : 객체생성없이 클래스명을 통하여 바로 접근 가능

⑦ 늦은초기화

코틀린에서는 멤버변수가 자동으로 초기화되지 않음
초기화를 미리 하지 않으면 에러 발생

onCreate()보다 멤버변수가 먼저 생성되는데, 멤버변수에게 값을 찾아오려면 onCreate()에서 view가 생성되어야 함...
이와 같이 당장 초기화가 어려운 상황에서 늦은초기화 이용

⑦-1. lateinit [var]
⒜ nullable 변수는 lateinit 불가
⒝ 기본자료형(8개)은 사용불가
어차피 기본값은 참조값이 아니기 때문에 굳이 값을 나중에 넣을 이유가 없음
⒞ val에는 사용불가

class Hello {
    lateinit var name:String

    fun onCreate() {
        name = "Sam" //이때 초기화됨
    }
}

⑦-2. by lazy [val]
⒜ nullable 변수에도 가능

val message:String? by lazy { null }

⒝ 기본자료형에도 가능
⒞ 조건값으로 값 대입 가능

val message3:String by lazy {
        if (age < 20) "미성년자"
        else "성인"
}

⒟ var 사용 불가능

class Hello {
    val address:String by lazy {"Seoul"} //이 변수가 처음 사용될 때 초기화됨
    val add:String = "Pusan" //만드는 순간 초기화됨

    val tel:String by lazy {
        println("늦은 초기화")
        "01012345678"
    }
}

0개의 댓글