KOTLIN

[Kotlin] 공부 6일차 (2022-01-18)

HJ39 2022. 1. 18. 02:04
더보기

▷ 클래스

    ▶ 클래스 선언

    클래스의 멤버

    객체 생성

 

  • 클래스
  • 클래스 선언
class User{ }

코틀린에서는 클래스의 생성자를 본문이 아닌 선언부에 작성할 수 있어서 본문이 없는 클래스도 의미가 있다.

 

  • 클래스의 멤버
class User{
	var name = "kkang"
	
	constructor(name: String){	//생성자
	this.name = name
	}

	fun someFun(){
	println("name : $name")
	}

	class SomeClass{ }
}

→ 생성자 : constructor라는 키워드로 선언한다.

→ 변수

→ 함수

→ 클래스

 

  • 객체 생성
val user = User("kim")
user.someFun()

객체를 생성할 때는 생성자가 자동으로 호출되므로 소괄호 안에 전달할 매개변수가 클래스에 선언된 생성자의 매개변수와 일치해야 한다.

 

  • 생성자

한 클래스 안에 주 생성자만 선언할 수도 있고 주 생성자와 보조 생성자 둘 다 선언할 수 있다.

 

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

→ constructor키워드로 클래스 선언부에 선언 (constructor 키워드 생략 가능)

→ 필수가 아니지만 한 클래스에 하나만 가능

→ 개발자가 생성하지 않으면 컴파일러가 자동으로 매개변수 없는 주 생성자를 생성

 

class User(name: String, count: Int){
	init{
	println("i am init...")
	}
}

fun main(){
	val user= User("kkang",10)
}

→ 주 생성자의 실행 영역에 중괄호 {}를 사용하기 위해서는 init이라는 키워드를 사용한다.

→ init키워드로 지정한 영역은 객체를 생성할 때 자동으로 실행된다.

 

□ 생성자의 매개변수를 클래스 내부 함수에서 사용 방법

class User(name: String, count: Int){
    var name: String
    var count: Int
    init{
        this.count=count
        this.name = name
    }
    fun someFun(){
        println("name: $name, count : $count")
    }
}

fun main(){
    val user= User("kkang",10)
    user.someFun()
}

실행결과
name: kkang, count : 10

→ 클래스 내부 함수에서 생성자 매개변수를 사용하기 위해서 클래스 내부에 클래스 멤버 변수를 선언해야 한다.

더보기

위 코드와 같은 코드

class User(val name: String, val count: Int){
    fun someFun(){
        println("name: $name, count : $count")
    }
}

fun main(){
    val user= User("kkang",10)
    user.someFun()
}

실행결과
name: kkang, count : 10

원래 매개변수를 선언할 때 var, val 키워드를 추가할 수 없지만 주 생성자만 유일하게 var, val키워드로 매개변수를 선언할 수 있다.

 

  • 보조 생성자

→ 클래스 본문에 constructor 키워드로 선언

→ 여러 개 추가 가능

class User(){
	constructor(매개변수: 반환타입){ ... }
}

 

  • 주 생성자와 보조 생성자 연결

클래스를 선언할 때 둘 중 하나만 선언하면 문제가 없지만, 만약 둘 다 선언한다면 반드시 생성자끼리 연결해주어야 한다.

class User(name: String){
    constructor(name:String, count:Int):this(name){
        println("countructor(name:String, count:Int) call...")
    }
    constructor(name:String, count:Int,email:String):this(name,count){
        println("constructor(name:String, count:Int,email:String)call...")
    }
}

fun main(){
    val user1= User("kkang1",10)
    val user2 = User("kkang2", 30,  "a@a.com")
}

실행결과
countructor(name:String, count:Int) call...
countructor(name:String, count:Int) call...
constructor(name:String, count:Int,email:String)call...

위 코드처럼 주 생성자와 보조 생성자를 선언할 경우 반드시 주 생성자가 실행되게 만들어야 한다.

 


 

  • 상속

→ 클래스를 선언할 때 다른 클래스를 참조해서 선언하는 것

→ 콜론 ':' 기호를 사용하여 상속한다.

open class Super{ }
class Sub: Super(){ }

→ 상속할 수 있게 상위 클래스에 open키워드를 사용한다.

→ Super를 상속받아 Sub 클래스를 선언한다.

 

  • 상위 클래스 생성자 호출
open class Super(name: String){ }

class Sub(name: String): Super(name){ } //상위클래스 생성자 호출문을 클래스 선언부에 작성

class Sub: Super{	//보조 생성자에서 상위클래스 생성자 호출
	constructor(name:String):super(name){ }
}

→ 상위 클래스 생성자를 호출할 때 Super()를 사용한다.

→ 만약 하위 클래스에 보조 생성자만 있다면 보조 생성자에서 super()을 사용한다.

 

  • 오버 라이딩
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()
}

→ 클래스 Super와 클래스 Sub는 서로 상속 관계이다.

→ 위 코드의 Super클래스를 오버 라이딩하였다.

open class Super{
    open var superData= 10
    open fun superFun(){
        println("i am superFun : $superData")
    }
}

class Sub:Super(){
    override var superData = 20
    override fun superFun(){
        println("i am sub class function : $superData")
    }
}

fun main(){
    val obj = Sub()
    obj.superFun()
}

→ 오버 라이딩할 때 오버 라이딩할 변수나 함수에 open키워드를 써야 하고 하위 클래스에 override 키워드를 써야 한다.

 

  • 접근 제한자

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

→ 코틀린은 4가지 접근 제한자가 있다.

접근 제한자 최상위에서 이용 클래스 멤버에서 이용
public 모든 파일에서 가능 모든 클래스에서 가능
internal 같은 모듈 내에서 가능 같은 모듈 내에서 가능
protected 사용 불가 상속 관계의 하위클래스에서만 가능
private 파일 내부에서만 가능 클래스 내부에서만 가능

→ internal : 같은 모듈 내에서 접근할 수 있는데, 모듈이라는 개념은 그래 들(Gradle)이나 메이븐(Maven) 같은 빌드 도구에서 프로젝트 단위 또는 같은 세트 단위를 가리킨다.

 


 

  • 클래스 종류
  • 데이터 클래스

→ data키워드로 선언하며 자주 사용하는 데이터를 객체로 묶어준다.

→ VO(value-object) 클래스를 편리하게 이용할 수 있게 해 준다.

 

□ 일반 클래스와 데이터 클래스를 비교하는 코드

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 nonData1 = NonDataClass("kkang","a@a.com",10)
    val nonData2 = NonDataClass("kkang","a@a.com",10)

    val data1 = DataClass("kkang","a@a.com",10)
    val data2= DataClass("kkang","a@a.com",10)

    println("non data class equals : ${nonData1.equals(nonData2)}")
    println("data class equals : ${data1.equals(data2)}")
}

→ data 클래스는 객체가 같은지 비교하는 것이 아닌 객체의 데이터가 같은지 비교한다.

 

□ 데이터 클래스 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 data1 = DataClass("kkang","@2@11",10,"1234")
    val data2 = DataClass("kkang","@2@11",10,"abcd")

    println("data1 & data2 equals : ${data1.equals(data2)}")


}
실행결과
data1 & data2 equals : true

→ 보조 생성자의 멤버 변수는 비교하지 않고 주 생성자 멤버 변수만 비교하여 판단한다.

 

□ 객체 데이터를 반환하는 toString() 함수

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 nonData = NonDataClass("kkang","a@a.com",10)
    val data = DataClass("kkang","a@a.com",10)

    println("non data class equals : ${nonData.toString()}")
    println("data class equals : ${data.toString()}")
}
실행결과
non data class equals : com.example.androidlab.NonDataClass@6fadae5d
data class equals : DataClass(name=kkang, email=a@a.com, age=10)

→ 일반 클래스 객체의 toString() 함수가 출력하는 값은 의미 있는 데이터가 아니다.

→ 데이터 클래스의 toString() 함수는 객체가 포함하는 멤버 변수의 데이터를 출력한다.

 

  • 오브젝트 클래스

→ 익명 클래스(anonymous class)를 만들 목적으로 사용된다.

→ 이름이 없으므로 선언과 동시에 객체를 생성해야 한다.

→ object라는 키워드를 사용한다.

 

□ 오브젝트 클래스 사용 예시 1

val obj = object {
    var data = 10
    fun some() {
        println("data : $data")
    }
}

fun main() {
    obj.data = 20
    obj.some()
}

실행결과
Error!
Error!

→ 클래스를 선언하며 객체를 obj변수에 저장하고 obj객체로 클래스에 선언한 멤버에 접근하려 했지만 오류가 난다.

→ object키워드로 클래스를 선언했지만 타입을 명시하지 않아서 이 객체는 최상위 타입인 Any로 취급한다.

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

 

□ 오브젝트 클래스 사용 예시 1

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()
}
실행결과
i am object some : 30

→ 오브젝트 클래스는 Super클래스의 상속을 받는다.

→ obj객체를 이용하여 Super클래스에 선언된 멤버에 접근할 수 있다.

 

  • 컴패니언 클래스

→ 멤버 변수나 함수를 클래스 이름으로 접근하고자 할 때 사용한다.(자바의 static 느낌이다)

→ 객체를 생성하지 않고 클래스 이름으로 특정 멤버를 이용할 수 있다.

→ companion 키워드 사용

 

□ 컴패니언 클래스의 멤버 접근

class Myclass{
    companion object{
        var data = 10
        fun some(){
            println(data)
        }
    }
}

fun main() {
    Myclass.data =20
    Myclass.some()
}
실행결과
20

→ companion object {} 형태로 선언하면 클래스 이름으로 접근할 수 있다.

 


 

  • 람다 함수

많은 프로그래밍 언어에서 제공하는 익명 함수

 

  • 람다 함수 규칙

→ { }로 표현한다

→ { } 안에 화살표(->)가 있고 화살표 왼쪽은 매개변수, 오른쪽은 함수 본문

→ 함수 반환 값은 함수 본문의 마지막 표현식이다

 

□ 람다 함수 선언 방법

일반 함수
fun sum(num1:Int, num2:Int):Int{
    return num1+num2
}

람다 함수
val sum1 = {no1:Int,no2:Int -> no1+no2}

→ fun 키워드를 사용하지 않고 함수 이름도 없다.

 

□ 람다 함수 호출

sum(10,20)

→ 변수에 대입하여 사용할 수 있다.

 

□ 람다 함수 선언 및 호출

{no1:Int,no2:Int -> no1+no2}(10,20)

→ 항상 변수에 대입할 필요 없이 바로 호출해서 사용할 수 있다.

 

  • 매개변수 없는 람다 함수
{-> println("function call")}
{println("function call")}

→ 람다 함수에 반드시 매개변수가 있을 필요는 없다.

→ 화살표도 생략 가능하다

 

  • 매개변수가 1개인 람다 함수
 val some = { no: Int -> println(no) }
 some(10)
 
 val some (Int) -> Unit = {println(it)}
 some(10)
 
 실행결과
 10
 10

→ (Int) -> Unit이 매개변수 1개인 람다 함수임을 알려준다

→ 중괄호 안에 매개변수 선언을 생략하고 println(it)처럼 it키워드로 매개변수를 이용할 수 있다.

 

  • 람다 함수의 반환

→ return 문을 사용할 수 없다.

val some = {no1:Int , no2:Int ->
    println("in lambda function")
    no1*no2}

println(some(10,20))

→ 마지막 줄의 실행 결과가 람다 함수의 반환 값이다.

 

 

'KOTLIN' 카테고리의 다른 글

[Kotlin] 공부 8일차 (2022-01-20)  (0) 2022.01.21
[Kotlin] 공부 7일차 (2022-01-19)  (0) 2022.01.19
[Kotlin] 공부 5일차 (2022-01-17)  (0) 2022.01.18
[Kotlin] 공부 4일차 (2022-01-15)  (0) 2022.01.16
[Kotlin] 공부 3일차 (2022-01-14)  (0) 2022.01.15