본문 바로가기

동방프로젝트

코틀린 2일차

fun <T> joinToString(
collection: Collection<T>,
separator: String= ", ",
prefix: String= " ",
postfix: String= " "
):String

joinToString(list, ",", "", "")
joinToString(list)
joinToString(list, "; ")
이렇게 함수 호출할 때 일부 인자를 쓰거나 안 쓸 수 있음. 오버로드 문제 x

이를 strings 패키지에 삽입 법:
package strings
fun joinToString(...) : String {...}
이렇게, 이 함수를 소스 파일의 최상위 수준에 넣어 모든 곳에서 import를 통해 사용이 가능
변수도 fun 바깥에 선언하므로써 정적으로 선언 가능

package strings
fun String.lastChar(): Char=this.get(this.length-1_
+
import strings.* 또는 import strings.lastChar
val c="Kotlin".lastChar()
또는
import strings.lastChar as last
val c="Kotlin".last, as키워드를 통해 임포트한 클래스나 함수를 다른 이름으로 부를 수 있음

fun<T> Collection<T>.joinToString(
separator: String= ", ",
prefix: String= " ",
postfix:String= " "
):String {
val result=StringBuilder(prefix)
for((index, element) in this.withIndex())
if(index>0) result.append(separator)
result.append(element)
}
result.append(postfix)
return result.toString()
}

>>>val list=listOf(1,2,3)
>>>println(list.joinToString(separator=";", .....)
this는 수신 객체를 가리킴. 위에서는, T타입 원소로 이뤄진 컬렉션
joinToString을 클래스의 멤버처럼 호출이 가능

문자열의 컬렉션에 대해서만 호출할 수 있는 join함수의 정의는 아래와 같음
fun Collection<String>.join(
separator: String= ", ",
prefix: String= " ",
postfix:String= " "
) =joinToString(separator, prefix, postfix)
>>>println(listOf("one", "tow", "eight").join(" "))

확장함수: 어떤 클래스의 멤버 메소드인 것처럼 호출할 수 있지만, 그 클래스 밖에 선언된 함수
이는 오버라이드가 불가
open class View { open fun click() = println("View clicked")
class Button: View() { override fun click() = println("Button clicked") }
위에서, button view를 오버라이드 한 상태.
아래에서 showoff는 클래스의 외부에서 선언된 확장함수
fun View.showOff() = println("I'm a view")
fun Button.showOff() = println("I'm a button")
>>> >>> val view: View=Button()
>>>view.showOff()
I'm a view ->view의 확장함수가 호출됨

<확장 프로퍼티>
일반적인 프로퍼티(lengthof)에 수신 객체 클래스가 추가됨
var StringBuilder.lastChar: Char
get() = get(length-1) //프로퍼티 게터
set(value: Char) {
this.setCharAt(length=1, value) //프로퍼티 세터
}

>>>println("Kotlin".lastChar)
n
>>>val sb=StringBuilder("Kotlin?":)
>>>sb.lastChar='!'
>>>println(sb)
Kotlin!

인자가 하나뿐인 일반 메소드나 확장 함수에 중위호출 사용법" INFIX변경자를 맨 앞에 선언
infix fun Any.to(other:Any) = Pair(this, other)
타입에 관계없이 임의의 순서쌍 만들기(to 수신객체는 제네릭)
fun <K,V> mapOf(vararg values: Pair<K,V>):Map(K,V)

String 확장함수를 이용해 경로 파싱하기
fun parsePath(path:String) {
val directory=path.substringBeforeLst("/")
val fullName=path.substringAfterLast("/")

val fileName=fullName.substringBeforeLast(".")
val extension=fullName.substringAfterLast(".")
println("Dir: " $directory, name:$fileName, ext:$extension")
}
>>>parsePath("/Users/yole/kotlin-book/chapter.adoc")

위를 정규식으로 파싱하면?
fun parsePath(path:String) {
val regex="""(.+)/(.+)\.(.+)""".toRegex()
val matchResult=regex.matchEntire(path)
if(matchResult!=null) {
val (directory,filename,extension)= matchResult.destructured
println("Dir: $directory, name:$filename, ext:$extension")
}
}

로컬함수를 이용한 코드중복 줄이기
class User(val id:Int, val name:String, val address:String)

fun saveUser(user:User) {
fun validate(user:User,
value:String,
fieldName: String) {
if(value.isEmtpy()) {
throw IllegalArgumentException(
"cam't save user ${user.id} : empty $fieldName")
}
}

validate(user, user.name, "Name")
validate(user, user.address, "Address") //로컬함수를 호출, 각 필드를 검증
}

이를, 로컬함수가 자신이속한 바깥함수의 파라미터와 변수에 접촉시키게 함으로써, user사용 안할 수 있음
class User(val id:Int, val name:String, val address:String)

fun saveUser(user:User) {
fun validate(value:String,
fieldName: String) {
if(value.isEmpty()) {
throw IllegalArgumentException(
"cam't save user ${user.id} : " + "empty $fieldName")
}
}

validate(user.name, "Name")
validate(user.address, "Address") //바깥함수 user 파라미터에 접근
}

이를 더 개선, 검증 로직을 user클래스를 확장한 함수로 변경
class User(val id:Int, val name:String, val address:String)

fun User.validateBeforeSave() {
fun validate(value:String,
fieldName: String) {
if(value.isEmpty()) {
throw IllegalArgumentException(
"cam't save user $id: empty $fieldName")
} //user의 프로퍼티를 직접 사용중
}

validate(name, "Name")
validate(address, "Address")
}

fun saveUser(user:User) {
user.validateBBeforeSave() //확장함수를 호출, user을 디비에 저장
}

'동방프로젝트' 카테고리의 다른 글

안드3일차 -1  (0) 2020.08.11
안드2일차  (0) 2020.08.10
안드1일차  (2) 2020.08.08
남방요척몽) 특별한 일 없으면 아직 바꿀 일 없을 player.cpp  (2) 2020.08.01
코틀린 1일차  (2) 2020.07.27