오류를 예방하는 타입 안정성 🧌 -1

Record For a Better Life ·2022년 9월 25일
0

다재다능코틀린

목록 보기
5/6

코틀린은 향상된 null체크, 스마트 타입 캐스팅, 유연한 타입 체킹을 이용해서 개발자들의 코드를 더욱 타입 안정적이면서도 적은 오류를 만들도록 최선을 다한다. NullPointerException 같은 경우에도 컴파일 시간에 최대한 빠르게 방지할 수 있도록 도와준다.

이번 장에서 다룰 내용은 Any와 Nothing 클래스, null 기능 참조와 관련된 연산자, 스마트 캐스트의 장점 등으로, 오류를 줄이고 코드의 유지보수를 쉽게 하도록 디자인하는 데 도움이 될 것이라고 한다. 👻

6-1 Any와 Nothing 클래스

코틀린의 Any 클래스는 자바의 Object에 대응되는 클래스라고 볼 수 있다.
Nothing 클래스는 함수가 아무것도 리턴하지 않을 경우 리턴하는 클래스이다. -> method가 하나 이상의 브랜치에서 아무것도 리턴하지 않을 경우 타입 체크를 한다면 Nothing 클래스가 있어야 유용하다.

1) Base Class 'Any'

  • 개발자로 하여금 최대한, 가끔은 조금 과하게 유연성을 제공한다. 제한적으로 사용할 필요가 있다고 한다.
  • 일반적으로는 모든 코틀린의 타입에 공통으로 적용되는 메소드를 만들기 위해 존재한다.
    ex> equals(), hashCode(), toString() method
  • 객체의 context 안의 코드 블럭을 실행할 때 많은 반복적이고, 장황한 코드들을 제거할 수 있다. (let(), run(), apply(), also()와 같은 확장함수 사용)

2) Nothing은 void보다 강력하다.

  • 함수가 진짜로, 아무것도 리턴하지 않는 상황에서 필요하다.
  • 인스턴스가 없고 값이나 결과가 영원히 존재하지 않을 것이라는 걸 나타낸다.
fun computeSqrt(n: Double): Double {
	if(n >= 0) {
    	return Math.sqrt(n)
    } else {
    throw RuntimeException("No negative please")
    }
}

if문 - Double 리턴, else문 - 예외처리 (Nothing 타입)

  • Nothing을 메소드의 리턴타입으로 사용한다면, 해당 함수가 절대로 리턴을 하지 않을 것을 의미, 함수 호출은 예외만 발생시킨다.

Nothing class는 블로그 글을 참고하며 이해해봤지만 아직 조금 애매한 것 같다. 이후 Unit과 비교해서 더 자세히 찾아보고 추가해야 할 듯 하다. 🤧

6-2 Null 가능 참조

1) null은 에러를 유발한다.

Java에서는 참조가 리턴되어야 할 메소드에서 null을 리턴할 때의 오류를 염려해도 해당 코드를 짜는 것을 막을 수 없다. 프로그래머는 Optional를 사용하는 방법을 선택해야 하지만 언제, 어디서 사용하는지 매우 혼란스럽다.

코틀린은 null을 null 불가 참조에 할당하거나 참조 타입이 null 불가인 곳에 리턴하려고 하면 컴파일 오류가 난다.(만약 자바라면 컴파일이 아닌, 실행 시간에서 오류가 날 것이다.)

  • 일반적으로, (Java와 상호 운용할 목적이 아니라면) null과 nullable 타입은 절대 사용하지 않는 편이 좋다.

2) Null 가능 타입

null 불가 타입들은 각자 대응하는 null 가능타입이 있다.
ex>
null 불가 : String -> null 가능 : String?

null이 될 수 있는 객체에 접근하기 전에 먼저 null 체크를 해줘야 한다.

if (name != null){
return name.reversed()
}
return null

null 체크가 너무 지저분하다. 이제 안정성은 유지하며 지저분한 코드를 제거하자 👍

세이프 콜 연산자 (Safe-call operator)

  • ?연산자를 이용하면 메소드 호출 또는 객체 속성 접근과 null 체크를 하나로 합칠 수 있다.
    위의 지저분한 코드를
  return name?.reversed() 

로 간단하게 바꿀 수 있다!

엘비스 연산자(Elvis Operator)

  • 좌측 표현식의 결과가 null이 아닐 경우 결과를 리턴,
    null일 경우 우측 표현식의 결과를 리턴 (오른쪽 표현식이 사용되지 않는 경우 연산 실행 x)
val result = name?.reversed()?.toUpperCase()
return if (result == null) "Joker" else result

  ⬇️

return name?.reversed()?.toUpperCase() ?: "Joker"  //엘비스 연산자 사용

not-null 확정 연산자 !!는 그냥 사용하지 마라.

6-3 타입 체크와 캐스팅

가끔 지금 가지고 있는 객체가 내가 예상한 특정 객체인지 궁금할 때가 있다. 그러면 해당 객체가 맞는지 검증을 하고, 특정 타입으로 캐스팅을 하면 원하는 메소드를 사용할 수 있다고 한다.

타입 체크

실행 시간 타입 체크에 대해선 논란이 많지만, 아주 유용하며, equals()메소드와 when을 사용할 때는 반드시 필요하다.

is 사용하기

  • 객체가 참조로 특정 타입을 가리키는지 확인
class Animal {
  	Override operator fun euqals(other: Any?) = other is Animal
  }

위 코드에서는 other이 Animal 클래스인지 확인한다. 예상된 타입이라면 true, 아니라면 false 리턴

  • is나 !is를 사용하면 캐스팅도 쉽게 가능하다!

스마트 캐스트

  • 코틀린에서는 참조의 타입이 확인되면 자동 혹은 스마트 캐스팅을 한다.
  • equals() 를 리팩토링하여 스마트 캐스트를 해보자
    override operator fun equals(other: Any?): Boolean {
    return if (other is Animal) age == other.age else false
    }
    ⬇️
    override operator fun equals (other: Any?) =
    other is Animal && age = other.age
profile
모든 것을 기록하는 벨로그 💻

0개의 댓글