[Kotlin]object/상속/익스텐션

dada·2021년 8월 26일
1

Kotlin

목록 보기
8/14
post-thumbnail

✅공부하기에 앞서!

기본적으로 kotlin은 java의 static과 멤버필드 사용 위치랑 똑같음

class hi {

    val good = ""

    fun test() {
        //a = "aaaa" final이라 변경 불가
        //b = "bbbb" final이라 변경 불가
        c = "cccc"  //인스턴스 메소드에서는 static필드 사용 가능
        run()  //인스턴스 메소드에서는 static메소드 호출 가능
    }

    companion object {
        val a: String = "" //static final, 런타임 시 값 결정됨 즉,독립적인 프로그램 수행 중에 프로그램 수행에 따라 값이 바뀔 수 있음
        const val b: String = "" //static final, 컴파일 시 값 결정됨
        var c = "" //static
        fun run() {
            //  test() -> static메소드 영역에서 인스턴스 메소드 호출 불가능
            //  good="" ->static메소드 영역에서 인스턴스 필드 사용 불가능
        }
    }
}

🚫companion object: static멤버를 한데 모아 코드블럭으로 묶어두기!

  • static 프로퍼티, 메서드에 일일이 static키워드 붙이지 않고 companion object{}로 묶어줌
  • 상수 만들때 companion object {const val 상수} 로 해준 이유임
    companion object->static특성 val->final특성
class Family {
    companion object {
        var number = 4
        var name = "백김치"
    }

    var happy = "yes"
}

fun main(args: Array<String>) {
   Family.number
   Family.name
   // Family.happy
}

👶상속

기억하고 있어야 할 기본 규칙 4개

  • 자식,부모 생성자는 프라이머리/세컨더리 각각에서 동시에 호출돼야함
    (자식은 프라이머리 생성자로 호출되고 부모는 세컨더리 생성자에서 호출되면 안됨)
class Child33(val value:String):Base2{
    super(value)
} //에러

  • 일반 클래스가 프라이머리, 세컨더리 생성자를 동시에 사용하거나 오버라이딩한 세컨더리 생성자를 this()로 호출할때의 상황과 혼동하지 말것
//세컨더리 생성자가 호출될 때 프라이머리 생성자를 반드시 호출하도록 해야됨
class Car(engine:String,body:String) {
    var door:String=""
    constructor(engine: String, body: String, door: String): this(engine,body){
    this.door=door
    } //세컨더리 생성자 호출하면서 프라이머리 생성자 호출하기
}

  • 부모생성자에 파라미터가 전역변수의 역할을 하고 있는 경우 부모생성자로 전달되는 파라미터는 이미 부모생성자에서 var val로 선언해두었기때문에 자식생성자에서 var val을 붙이면 안됨(자식생성자에서만 선언하는 파라미터는 가능.)
open class Charator(var hp: Int, val power: Int) {
    open fun defense(damage: Int) {
        hp -= damage
        if (hp > 0) println(" ${javaClass.simpleName} 의 남은 체력은 $hp 입니다")
        else println("사망했습니다")
    }
}
//자식생성자에서 var val을 붙이면 안됨
class SuperNight(hp: Int, power: Int, val heal:Int) : Charator(hp, power) {
    override fun defense(damage: Int) {
        super.defense(damage - 2)
    }
}

  • 세컨더리 생성자에서 같이 호출하는 경우, 부모 생성자는 super()로 호출되어야함
open class Base {}

class Child2:Base{
//constructor():Base() 
//불가능!!!super() 로 호출해야됨 자바를 기억해

1. 부모 프라이머리 생성자+파라미터X

  • 상속 대상이 되는 class는 open 키워드로 만들어야 자식 클래스에서 사용 가능
open class Base {}

1. 프라이머리 생성자에서 같이 호출
class Child(name: String) : Base() {}

2. 세컨더리 생성자에서 같이 호출
class Child2:Base{
 constructor():super()}
//자식 생성자 호출될 때 부모 클래스의 프라이머리 디폴트 생성자 호출
//constructor():Base() 불가능!!!super() 로 호출해야됨 자바를 기억해

2. 부모 프라이머리 생성자+파라미터O

  • 자식클래스 생성자 호출될 때 입력하는 파라미터를 부모 생성자 파라미터로 전달하는 개념
  • 부모class에 있는 생성자가 프라이머리 생성자든, 세컨더리 생성자든 자식이 부모 생성자 호출할때 프라이머리,세컨더리에서 같이! 호출해주면됨
open class Base(value: String) {}

1. 프라이머리 생성자에서 같이 호출
class Child(value: String, val name: String) : Base(value) {} 
class Child2(value: String) : Base2(value) {}

2. 세컨더리 생성자에서 같이 호출
class Child22 : Base2 {
    constructor(name: String) : super(name)
}

3. 부모 세컨더리 생성자+파라미터X

open class Base3 {    //부모 클래스는 open되어 있어야함
    constructor()
}

1. 프라이머리 생성자에서 같이 호출
class Child1:Base3() {}
class Childddd(name:String):Base333(){}

2. 세컨더리 생성자에서 같이 호출
class Child2:Base3{
    constructor(name:String):super()
}

4. 부모 세컨더리 생성자+파라미터O

open class Base3 {    //부모 클래스는 open되어 있어야함
    constructor(name:String)
}

1. 프라이머리 생성자에서 같이 호출
class Child1(name:String):Base3(name) {}
class Childddd(age:Int,name:String):Base333(name){}

2. 세컨더리 생성자에서 같이 호출
class Child2:Base3{
    constructor(name:String):super(name)
}

🕵️‍♀️자식클래스와 생성자, 접근제한자

  • 객체를 만들 수 있냐는 생성자의 접근제한자가 관여하는것
  • private class{}도 객체 생성가능 함. 자식 class를 못 만드는 거임.
 private class mother{
 // class는 접근 제한자 안붙어있으면 원래 private이 기본.
 //private는 생략이 가능해서 그냥 class mother{}이면 자식 클래스 생성 불가
 // 기본=private class=자식 클래스 생성 불가=생성자 private아니니까 객체 생성은 가능
     constructor()
     fun dabin(){}
}
open class mother1{
    private constructor()
    constructor(hi:String)
}

//class child:mother(){}  
//private class는 자식 클래스 생성 불가

//class child1:mother1(){}  
//mother() 호출은 해당 부모 생성자가 private이라 호출 불가 

class child2(hi:String):mother1(hi){} 
//보무 생성자 중 private아닌 생성자 호출해서 클래스 생성 가능


fun main(args: Array<String>) {

    mother().dabin()  
    //private class 역시도 생성자 호출해서 객체 생성이 가능! 메서드 필드 호출도 됨
    
    //mother1()  외부에서 객체 생성을 불가능하게 하려면 생성자가 private이여야함
    //mother().num

👼메서드, 프로퍼티 오버라이딩

  • 부모클래스,오버라이딩 될 프로퍼티,메서드 모두 open 작성
  • 오버라이딩 시 앞에 override 작성
open class BaseClass {
    open fun opend() {}
    open var open = 6
    fun notOpend() {}
}

class ChildClass : BaseClass() {
    override fun opend() {} //오버라이딩 할때 앞에 override작성!
    override var open = 7
    //override fun notOpend() open되어 있지 않아서 오버라이딩 불가능
}

open class Car22 {
    open fun drive(): String {
        return "달린다"
    }
}

class superCar : Car22() {
    override fun drive(): String {
        return "빨리 ${super.drive()}"
    }
}

🌈익스텐션

  • 익스텐션: 이미 만들어져있는 클래스,메서드,프로퍼티에 대해 익스텐션을 지원
  • 상속이 미리 만들어져 있는 클래스를 가져다 쓰는 개념이라면, 익스텐션은 미리 만들어져 있는 클래스에 메서드를 넣는 개념
  • 자신이 만든 클래스에 사용하기 보다는 누군가 작성해둔 이미 컴파일되어 있는 클래스에 메서드를 추가하는 용도로 많이 사용
  • 익스텐션을 사용한다고 해서 실제 클래스의 코드가 변경되는 것은 아님. 단지 실행 시 도트 연산자로 호출해서 사용할 수 있도록 함
  • 거의 메서드 확장 용도로 사용

fun 확장하고싶은 클래스.내가 만드는 메서드(){//정의}

fun String.plus(word: String): String {
    return this + word
}

fun main(args: Array<String>) {
    var nice = "안녕"
    println(nice.plus("반가워"))  //안녕 반가워
}
profile
'왜?'라는 물음을 해결하며 마지막 개념까지 공부합니다✍

0개의 댓글