티스토리 뷰

함수

  • 값을 반환하지 않는 함수는 Unit타입을 반환하며 생략 가능 (Java의 void와 같음)
class Foo{
	fun foo(): Unit{ //반환값이 없는 함수, Unit 생략 가능
    	//함수 구현
    	}
    
    	fun bar(): Int{ //정수형을 반환하는 함수
    		return 0
    	}
}

상속 및 인터페이스 구현

  • 코틀린에서는 상속과 구현 상관없이 세미콜론(:) 뒤에 부모 클래스와 인터페이스를 표기
  • 클래스를 상속받는 경우 반드시 부모 클래스의 생성자를 호출해야함
  • 상속받거나 구현한 함수의 앞에 반드시 override 키워드를 붙혀야함
class MainActivity: AppCompatActivity(), View.OnClickListener{ //부모 클래스의 생성자 호출
	
    //AppCompatActivity 클래스를 상속박아 onCreate()메소드 오버라이딩
    override fun onCreate(savedInstanceState: Bundle?){ 
    	super.onCreate(savedInstanceState)
    }
    
    //View.OnclickListener 인터페이스 구현
    override fun onClick(v: View) {
    }
}
  • 코틀린에서는 open 키워드가 붙은 클래스와 함수만 재정의 가능
open class OpenClass { //상속 가능한 클래스
	open val openProperty = "open" //상속받은 클래스에서 재정의 가능한 프로퍼티
    	open fun openFuntion() {} //상속받은 클래스에서 재정의 가능한 함수
}

classFinalClass: OpenClass() { //OpenClass를 상속받는 클래스
	override val openProperty = "final" //프로퍼티를 재정의
    	override fun openFuntion() { println("open funtion") } //함수를 재정의
}

this

  • 해당 키워드를 사용한 클래스 자신을 지칭할 때 사용
  • 단독 사용시 해당 위치에서 가장 가까운 범위의 클래스를 의미
  • this@{클래스 이름}으로 다른 클래스를 가리킬 때 사용 가능

정적 필드 및 메소드

  • 클래스 내에 상수를 정의하거나 인스턴스 생성 없이 사용할 수 있는 메소드를 만들기 위해 사용
  • companion object : 클래스별로 하나씩 정의할 수 있는, 클래스의 인스턴스 생성 없이 사용할 수 있는 오브젝트(object)
//생성자가 private으로 선언되어 있으므로 외부에서는 접근 불가능
class User private constructor(val name: String, val registerTime: Long) {
	
    //companion object는 클래스 내부에 존재하므로 private 생성자에 접근 가능
    companion object {
    	fun create(name:String): User {
        	return User(name, System.currentTimeMillis())
        }
    }
}

//함수 호출 방법
User.create("yejin")

 


제네릭

  • 인자로 사용하는 타입에 따라 구체화되는 클래스나 인터페이스를 의미
  • 코틀린에서는 반드시 제네릭 클래스에 타입을 넣고 선언을 해야함
//컴파일 성공
val names: List<String>
val entries: Map<String, String>

//제네릭 클래스 타입을 넣지 않아 컴파일 실패
val names: List
  • 제네릭을 클래스/인터페이스 정의
//Car 클래스 정의
class Car { }

//항목을 담거나 빼는 함수가 있는 제네릭 인터페이스 Container 정의
//interface Container<T: Car>로 정의한다면 Container인터페이스는 Car 클래스 및 그 하위 클래스만 받을 수 있음
interface Container<T> {
	fun put(item: T)
    	fun take(): T
}

//Car를 담거나 뺄 수 있도록 인터페이스를 구현하는 Garage 클래스 정의
class Garage: Container(Car) {
	override fun put(item: Car){
    	}
    	override fun take(): Car {
    	}
}
  • 타입이 정의되어 있는 제네릭을 인자로 받거나 호출 시점에 타입을 지정하는 함수 정의
//타입이 정의되어 있는 제네릭을 인자로 받는 함수
fun processItems(items: List<String>){
}

//호출시점에 타입이 정해지는 제네릭을 인자로 받는 함수
fun <T> processItems(items:List<T>){
}
  • 호출 시점에 타입이 정해지는 제네릭을 인자로 받는 경우, 하위 또는 상위 타입을 받도록 지정 가능
  • in T : T의 상위 타입 제한, input의 약자이며 write만 가능
  • out T : T의 하위 타입 제한, output의 약자이며 read만 가능
open class Car {...}
class Sedan: Car() {...}
class Truck: Car() {...}

//src로 받은 목록을 dest에 추가
//dest는 T의 상위 타입을 제한, src는 T의 하위타입을 제한한다
fun <T> append(dest: MutableList<in T>, src: List<out T>) {
	dest.addAll(src)
}

val cars: MutableList<Car> = ...
val sedan: List<Sedan> = ...
val truck: List<Truck> = ...

append(cars, sedan)
append(cars, truck)

 


예외

  • throw로 예외를 발생시키고, try-catch 및 finally 문을 사용하여 예외 처리
//throw로 IllegalArgumentException를 발생시키는 예시
fun checkAge(age: Int) {
	if(age<0){
    	throw IllegalArgumentException
        	("Invalid age: $age")
}

val valid: Boolena = try {
	//예외를 발생시키는 코드
    	...
    
    	//예외가 발생하지 않았을 경우 true 반환
} catch (e: Exception) {
	//예외가 발생했을 때 수행할 동작
    	...
    
    	//동작 수행 후 false 반환
    	false
} finally {
	//예외 발생 여부와 상관없이 수행할 동작
}

 


NULL 안정성

  • 코틀린에서는 모든 타입에 명시적으로 널 허용 여부 표기  ex) @Nullable, @NonNull
  • 별도 표기가 없을 경우 널 값을 허용하지 않으므로, 널 값을 가질 수 있고록 하려면 타입 뒤에 ?를 붙여줘야 함
//컴파일 성공
val nullableString: String? = null //null값을 가질 수 있도록 '?'표기
val nonNullString: String = "Foo" //null값이 아닌 값으로 초기화

//컴파일 실패
val name: String //null을 허용하지 않는 값을 초기화하지 않아 에러 발생
val address: String = nul //null을 허용하지 않는 값에 nulldmf 대입했으므로 에러 발생
  • 함수의 파라미터와 반환 값에도 동일하게 적용
//line2의 인자로 null값 허용
fun formatAddress(line1: String, line2: String?, city: String): String {...}

//입력한 주소에 해당하는 우편번호를 반환하지만, 검색 결과가 없을 경우 null 반환
fun findPostalCode(address: String): PostalCode? {...}

//line1의 인자로는 null을 허용하지 않으므로 에러 발생
formatAddress(null, null, "Seoul")

//postaclCode 값은 null을 허용하지 않으나, findPostalCode 함수는 null값 반환 가능
val postalCode: PostalCode = findPostalCode("1600 Amphitheatre Pkwy")
  • 엘비스 연산자(?:) : 널 값을 허용하지 않는 값 혹은 변수에 널 값을 반환할 수 있는 함수의 결과를 처리하기 위해 사용
//기본 형식
foo ?: bar //foo가 null이 아닐 경우에는 foo를, null이라면 bar를 반환

//입력한 주소에 해당하는 우편번호를 반환하지만, 검색 결과가 없을 경우 null 반환
fun findPostalCode(address: String): PostalCode? {...}

//findPostalCode가 null값을 반환하는 경우 PostalCode.NONE값을 postal에 대입
val postal1: PostalCode = finfPostalCode("1600 Amphiteeatre Pkwy") ?: PostalCode.NONE

fun generateMapImage(address: String): Image? {

    //우편변호 검색 결과가 없을 경우 바로 함수 실행을 종료하고 결과로 null 반환
    val postal2 = findPostalCode(address) ?: return null
    ...
}
  • 안전한 호출(?.) 연산자 : 객체가 널 값이 아닌 경우에만 연산자 뒤의 문장을 수행하여, 널 값 확인과 값 접근/함수 호출을 한번에 수행
//기본 형식
val foo = bar?.baz //bar가 null이 아닐 경우에만 bar.baz를 대입, 그렇지 않으면 null 대입
foo?.bar() //foo가 null이 아닐 경우에만 bar() 호출
  • 안전한 자료형 변환(as?) 연산자 : 자료형 변환이 실패할 경우 널 값을 반환하여, 불가능한 자료형 변환을 해결
val foo: String = "foo"
val bar: Int? = foo as? Int //자료형 변환에 실패하면 null값이 대입되므로 bar가 null값을 허용하도록 Int?로 정의
val bar: Int = foo as? Int ?: 0 //변환에 실패할 경우 기본값을 0으로 지정
  • 널 값이 아님을 명시하는 비 널 값 보증(!!) : 널 값을 포함할 수 있는 타입을 널 값을 포함하지 않는 타입으로 변환하여 사용
//foo는 null을 포함할 수 있는 Foo 타입
val foo: Foo? = ...

//값 foo는 null값을 포함하지 않음을 보장
val nonNullFoo: Foo = foo!!

//값 foo가 null이 아님을 보장하면서 bar() 함수 호출
foo!!.bar()

//값 foo가 null이 아님을 보장하면서 baz 프로퍼티에 접근
val myBaz = foo!!.baz

//address와 line2 모두 null이 아님을 보장하지만 중첩 사용은 권장하지 않음
val line: String = contact.address!!.line2!!
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함