Kotlin function

2 minute read

코틀린 함수(Kotlin Method)

  • 코틀린 함수 기본 형태
    • fun을이용해서 정의, void를 사용하지 않음, 리턴타입의 위치가 틀림
    • 코틀린 함수 예제

        fun 함수명(변수) {
        }
      
        fun 함수명(변수): 리턴타입 {
        	return 
        }
      
        private fun loadRawData() = runSubtask("parse: ${file.name}") {
                try {
                    file
                        .readLines(charset)
                        .map { line ->
                            parser.parse(line)
                        }
                        .filter { rawFilter.filter(it) }
                        .map { line -> line.toTypedArray() }
                } catch (ex: FileNotFoundException) {
                    log.error("파일이 존재하지 않습니다 - $file", ex)
                    null
                }
            }
      
  • 코틀린에서는 함수를 클래스 안에 선언할 필요가 없음
  • 파라미터에 default를 지정하여 함수 overloading을 대신할 수 있음
  • 파라미터 이름을 지정하여 호출할 수 있음
    • default가 있는 경우 이름을 지정하지 않는 경우 순서대로 뒤에 있는 것을 생략 가능
    • default가 있는 경우 이름을 지정하는 경우에는 필요한 것만 지정해서 호출 가능
    • 이름을 지정할 경우 java와의 호환성 이슈 생길 수 있음
    • java에서는 @JvmOverloads를 붙이면 오버로딩 함수들을 자동으로 생성시켜줌
  • Method Override
    • java처럼 오버라이드를 위한 명시적인 수정자가 필요하지 않음
    • 멤버가 오버라이드 가능하다는 것을 나타내기 위해 open이라는 키워드 사용
    • 오버라이드 하고 있다는 것을 나타내기 위해 override 키워드 사용
    • override 표시된 멥버는 자체가 open이므로 하위 클래서에서는 다시 오버라이드 가능
  • Property Override (속성 오버라이드) -

범위 지정 함수 : apply, run, with, also, let

  • 기능정리 : https://kotlinworld.com/255
  • 기능비교 : https://stackoverflow.com/questions/45977011/example-of-when-should-we-use-run-let-apply-also-and-with-on-kotlin
  • 범위 지정함수는 수신 객체수신 객체 지정 람다(Lambda with receiver)로 구성
  • with()
    • 객체 이름 반복 사용을 피하기 위해 사용
    • 일반함수는 일반람다, 확장함수는 수신객체지정람다
    • 수신객체에 대한 작업 후 마지막 라인 리턴, run과 똑같이 동작 (객체전달방식만 다름)
    • run은 확장함수로 사용되고, with는 수신객체 파라미터로 받아 사용
    • 보통 run을 사용하고 with는 잘 사용하지 않는 듯…
      inline fun <T, R> with(receiver: T, block: T.() -> R): R {
          return receiver.block()
      }
    
      // examples
      var r: R = with(T()) { this.foo(); this.toR() }
    
      val person: Person = getPerson()
      with(person) {
          print(name)
          print(age)
      }
    
  • run()
    • 매개 변수로 전달된 명시적 수신객체를 암시적 수신 객체로 변환 할때 run()을 사용할수 있음
      inline fun <T, R> T.run(block: T.() -> R): R {
          return block()
      }
    
      // examples
      var r: R = T().run { this.foo(); this.toR() } // 수행결과를 리턴
    
      val inserted: Boolean = run {
          // person 과 personDao 의 범위를 제한 합니다.
          val person: Person = getPerson()
          val personDao: PersonDao = getPersonDao()
          personDao.insert(person)    // 수행 결과를 반환 합니다.
      }
    
      fun printAge(person: Person) = person.run {
          print(age)    // person 을 수신객체로 변환하여 age 값을 사용합니다.
      }
    
  • let()
    • 널이 될 수 있는 값을 널이 아닌 값만 인자로 넘김
    • let를 사용할 때 수신객체가 널인지 검사하기 위해서는 ?.을 사용하여 호출
      inline fun <T, R> T.let(block: (T) -> R): R {
          return block(this)
      }
      // examples
      var r: R = T().let { it.foo(); it.toR() }
    
      getNullablePerson()?.let {
          promote(it)    // null 이 아닐때만 실행됩니다.
      }
      val driversLicence: Licence? = getNullablePerson()?.let {
          // nullable personal객체를 nullable driversLicence 객체로 변경합니다.
          licenceService.getDriversLicence(it)
      }
      val person: Person = getPerson()
      getPersonDao().let { dao ->
          dao.insert(person) // 변수 dao 의 범위는 이 블록 안 으로 제한 됩니다.
      }
    
  • apply()
    • apply는 also와 마찬가지로 수신 객체를 반환
    • 수신 객체 람다 내부에서 수신 객체의 함수를 사용하지 않고 수신 객체 자신을 다시 반환 하려는 경우에 apply 를 사용
      inline fun <T> T.apply(block: T.() -> Unit): T {
          block()
          return this
      }
      // examples
      var t: T = T().apply { this.foo() }
    
      val peter = Person().apply {
          // apply 의 블록 에서는 오직 프로퍼티 만 사용합니다!
          name = "Peter"
          age = 18
      }
    
  • also()
    • also는 apply 와 마찬가지로 수신 객체를 반환
    • 블록 함수가 다른 값을 반환 해야하는 경우에는 also 를 사용할수 없음, 다른 값을 반환하려면 run을 사용
      inline fun <T> T.also(block: (T) -> Unit): T {
          block(this)
          return this
      }
      // examples
      var t: T = T().also { it.foo() }
    
      class Book(author: Person) {
          val author = author.also {
            requireNotNull(it.age)
            print(it.name)
          }
      }
    

Leave a comment