새소식

카테고리 없음

코틀린 클래스

  • -

클래스 선언

class User{ }
  • 클래스의 멤버
class User {
    var name ="google"
    constructor(name: String) {
        this.name = name
    }
    fun someFun() {
        println("name : $name")
    }
    class SomeClass { }
}

코틀린의 생성자는 constructor라는 키워드로 선언하는 함수

  • 객체 생성과 멤버 접근
val user = User("goo")  //객체를 생성하는 코드
user.someFun()

객체를 생성할 때  생성자가 자동으로 호출되므로 소괄호 안에 전달한 인자는 클래스에 선언된 생성장자의 매개변수와 들어맞아야 한다. 앞에서 작성한 User크래스의 생성자는 constructor(name:google)이므로 문자열 데이터를 전달받는 매개변수가 있습니다.

 

주 생성자

  • 주 생성자 선언
class User constructor() {
    
}

주 생성자는 constructor 키워드로 클래스 선언부에 선언한다.

주 생성자의 매개변수

  • 주 생성자의 매개변수
class User(name: String, count: Int) {
    
}

앞에 코드는 User클래스를 선언하면서 주 생성자에 매개변수를 2개 선언했다.

  • 매개변수가 있는 생성자 호출
val user = User("kkang", 10)

객체를 생성할 때 매개변수의 타입과 개수에 맞는 인자를 전달해야 한다.

  • init 키워드로 주 생성자의 본문 지정
class User(name: String, count: Int) {
    init {
        println("i am init....")
    }
}
fun main() {
    val user = User("google", 10)
}

User라는 클래스에 주 생성자를 선언하고 클래스 본문에 init 여역을 두어 주 생성자의 본문을 작성했습니다.

이렇게 하면 main()함수에서 User 클래스의 객체를 생성할 때 init 영역에 작성한 코드가 자동으로 실행됩니다.

 

생성자의 매개변수를 클래스의 멤버 변수로 선언하는 방법

  • 생성자의 매개변수를 init 영역에서 사용하는 예
class User(name: String, count: Int) {
    init {
        println("name: $name, count : $count")  //성공!
    }
    fun someFun() {
        println("name : $name, count : $count") //오류!
    }
}

생성자를 호출할때 init 영역이 실행되므로 이곳에서 생성자의 매개변수에 접근할수 있다.

but, 생성자의 매개변수는 지역 변수이므로 다른 함수에서는 사용할 수 없습니다.

  • 생성자의 매개변수를 다른 함수에서 사용하는 예
class User(name: String, count: Int) {
    //클래스 멤버 변수 선언
    var name: String
    var count: Int
    init {
        //클래스 멤버 변수에 생성자 매개변숫값 대입
        this.name = name
        this.count = count
    }
    fun someFun() {
        println("name: $name, count : $count")  //성공!
    } 
}
fun main() {
    val user = User("google", 10)
    user.someFun()
}
  • 생성자의 매개변수를 클래스의 멤버 변수로 선언하는 방법
class User(val name: String, val count: Int) {
    fun someFun() {
        println("name : $name, count : $count") //성공!
    }
}
fun main() {
    val user = User("google", 10)
    user.someFun()
}

주 생성자에서만 유일하게 var나 val키워드로 매개변수를 선언할 수 있으며 이렇게 하면 클래스의 멤버 변수가 됩니다.

 

보조생성자

보조 생성자는 클래스의 본문에 constructor 키워드로 선언하는 함ㅁ수 입니다.

클래스는 본문에 선언하므로 여러 개를 추가할 수 있습니다.

  • 보조 생성자 선언
class User {
    constructor(name: String) {
        println("constructor(name: String) call...")
    }
    constructor(name: String, count: Int) {
        println("constructor(name: String, count: Int)call....")
    }
}
fun main() {
    val user1 = User("google")
    val user2 = User("google", 10)
}

보조 생성자에 주 생성자 연결

주 생성자와 보조 생성자를 모두 선언한다면 반드시 생성자끼리 연결해 주어야 한다.

  • 주 생성자와 보조 생성자 선언 시 오류
class User(name: String) {
    constructor(name: String, count: Int) { //오류!
        (..생략..)
    }
}
  • 보조 생성자에서 주 생성자 호출
class User(name: String) {
    constructor(name: String, count: Int): this(name) { //성공!
        //생략
    }
}
fun main() {
    val user = User("google", 10)
}
  • 보조 생성자가 여럿일 때 생성자 연결
class User(name: String) {
    constructor(name: String, count: Int): this(name) {
        //..생략..
    }
    constructor(name: String, count: Int, email: String): this(name, count) {
        //..생략..
    }
}
fun main() {
    val user = User("google, 10, "a@a.com")
}

 

클래스를 재사용하는 상속

 

상속과 생성자

  • 클래스 상속 형식
open class Super {  //상속 할수 있는 open 키워드 이용
}
class Sub: Super() {    //Super를 상속받아 Sub 클래스 선언
}

클래스를 선언할 때 다른 클래스를 참조해서 선언하는 것을 상속inheritance라고 한다.

코틀린에서 어떤 클래스를 상속받으려면 선언부에 코론(:)과 함께 상속받을 클래스 이름을 입력 합니다.

  • 매개변수가 있는 상위 클래스의 생성자 호출
open class Super(name: String) {
}
class Sub(name: String): Super(name) {
}
  • 하위 클래스에 보조 생성자만 있는 경우 상위 클래스의 생성자 호출
open class Super(name: String) {
}
class sub: Super {
    constructor(name: String): super(name) {
    }
}

오버라이딩 - 재정의

  • 상속 관계인 두 클래스
open class Super {
    var superData = 10
    fun superFun() {
        println("i am superFun : $superData")
    }
}
class Sub: Super()
fun main() {
    val obj = Sub()
    obj.superData = 20
    obj.superFun()
}

상위 클래스에 정의된 멤버(변수, 함수)를 하위 클래스에서 자신의 멤버처럼 사용할수 있다.
main함수에서 Sub클래스의 객체를 생성한 후 이 객체를 이용해 superData와 superFun() 함수를 사용했다.

 

 

상위 클래스에 선언된 변수나 함수를 같은 이름으로 하위 클래스에서 다시 선언하는 것을 오버라이딩 이라고 한다.

  • 오버라이딩의 예
open class Super {
    open var someData = 10
    open fun someFun() {
        println("i am super class function : $someData")
    }
}
class Sub: Super() {
    override var someData = 20
    override fun someFun() {
        println("i am sub class function : $someData")
    }
}
fun main() {
    val obj = Sub()
    obj.someFun()
}

코틀린에서 오버라이딩 규칙은 먼저 상위 클래스에서 오버라이딩을 허용할 변수나 함수 선언 앞에 open 키워드를 추가하는 것입니다.

그리고 open 키워드로 선언한 변수나 함수를 하위 클래스에서 재정의 할 때는 반드시 선언문 앞에 override라는 키워드를 추가해야 한다.

 

접근 제한자

클래스의 멤버를 외부의 어느 범위까지 이용하게 할 것인지를 결정하는 키워드 입니다.

접근 제한자 최상위에서 이용 클래스 멤버에서 이용
public 모든 파일에서 가능 모든 클래스에서 가능
internal 같은 모듈 내에서 가능 같은 모듈 내에서 가능
protected 사용 불가 상속 관계의 하위 클래스에서만 가능
private 파일 내부에서만 이용 클래스 내부에서만 이용
  • 접근 제한자 사용 예
open class Super {
    var publicData = 10
    protected  var protectedData = 20
    private var privateData = 30
}
class Sub: Super() {
    fun subFun() {
        publicData++    //성공!
        protectedData++ //성공!
        privateData++   //오류!
    }
}
fun main() {
    val obj = Super()
    obj.publicData++    //성공!
    obj.protectedData++ //오류!
    obj.privateData++   //오류!
}

코들린의 클래스 종류

  • 데이터 클래스 선언
class NonDataClass(val name: String, val email: String, val age: Int)

data class DataClass(val name: String, val email: String, val age: Int)
  • 데이터 클래스 객체 생성
fun main() {
    val non1 = NonDataClass("google", "a@a.com", 10)
    val non2 = NonDataClass("google", "a@a.com", 10)
    
    val data1 = DataClass("google", "a@a.com", 10)
    val data2 = DataClass("google", "a@a.com", 10)
}

객체의 데이터를 비교하는 equals()함수

  • 객체의 데이터를 비교하는 equals()함수
println("non data class equals : ${non1.equals(non2)}")         //결과값: false
        println("data class equals : ${data1.equals(data2)}")   //결과값: true
  • 데이터 클래스의 equals() 함수
data class DataClass(val name: String, val email: String, val age: Int) {
    lateinit var address: String
    constructor(name: String, email: String, age: Int, address: String):
            this(name, email, age) {
                this.address = address
            }
}
fun main() {
    val obj1 = DataClass("google", "a@a.com", 10, "seoul")
    val obj2 = DataClass("google", "a@a.com", 10, "busan")
    println("obj1.equals(obj2) : ${obj1.equals(obj2)}")
}

데이터 클래스의 equals() 함수는 주 생성자의 멤버 변수가 같은지만 판단 합니다.

  • 데이터 클래스의 toString() 함수
fun main() {
    class NonDataClass(val name: String, val email: String, val age: Int)
    data class DataClass(val name: String, val email: String, val age: Int)
    val non = NonDataClass("google", "a@a.com", 10)
    val data = DataClass("google", "a@a.com", 10)
    println("non data class toString : ${non.toString()}")
    println("data class toString : ${data.toString()}")
}

실행결과

non data class toString : com.example.test4.ch2.Test2Kt$main$NonDataClass@61bbe9ba
        data class toString : DataClass(name=google, email=a@a.com, age=10)

 

오브젝트 클래스
오브젝트 클래스는 익명 클래스 를 만들 목적으로 사용

val obj = object {
    var data = 10
    fun some() {
        println("data : $data")
    }
}
fun main() {
    obj.data = 20   //오류!
    obj.some()      //오류!
}

object 키워드로 클래스를 선언했지만 타입을 명시하지 않았으므로 이 객체는 코틀린의 최상위 타입인 Any로 취급합니다.

그런데 Any타입 객체에는 data, some()이라는 멤버가 없어서 오류가 발생한다.

그래서 오브젝트 클래스를 선언하는데 보통은 타입까지 함께 입력해서 선언한다.

오브젝트 클래스 타입은 object 뒤에 콜론(:)을 입력하고 그 뒤에 클래스의 상위 또는 인터페이스를 입력한다.

  • 타입을 지정한 오브젝트 클래스
open class Super {
    open var data = 10
    open fun some() {
        println("i am super some() : $data")
    }
}
val obj = object : Super() {
    override var data = 20
    override fun some() {
        println("i am object some() : $data")
    }
}
fun main() {
    obj.data = 30   //성공!
    obj.some()      //성공!
}

 

 

캠패니언 클래스

멤버 변수나 함수를 클래스 이름으로 접근하고자 할 때 사용한다.

class MyClass {
    var data = 10
    fun some() {
        println(data)
    }
}
fun main() {
    val obj = MyClass()
    obj.data = 20   //성공!
    obj.some()      //성공!
    MyClass.data = 20   //오류!
    MyClass.some()      //오류!
}

MyClass의 객체를 생성 한 후  객체명으로 멤버에 접근하는 데는 문제가 없다.

  • 캠피니언 클래스의 멤버 접근
class MyClass {
    companion object {
        var data = 10
        fun some() {
            println(data)
        }
    }
}
fun main() {
    MyClass.data = 20   //성공!
    MyClass.some()      //성공!
}

클래스의 내부에 companion objcet { } 형태로 선언하면 이 클래스를 감싸는 클래스 이름위 소스에서는 MyClass으로 멤버에 접근한다.

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.