'간단 공부 끝'에 해당되는 글 1건

쓸 데 없이 오래 걸렸다. 오래 걸린 이유가 있다.

IntelliJ, JetBrain은 나에게 똥을 줬다. IntelliJ Education 은 아주 쓰레기였다. 툭하면 강제 종료를 유발했다.

 

결국 껐다 켰다를 반복하며 학습을 계속하다, 종래엔 프로그램이 아예 작동하지 않았다.

프로그램을 끄고 다시 켜도 그 지경이었다. 캐쉬도 삭제해보고, 프로그램을 삭제하고 다시 설치해보기도 했다.

 

결과는 똑같았다. 이 개똥같은 놈.

 

그래서 공부 방법을 바꿨다. 차라리 책을 샀으면 편하기라도 했을텐데...

 

일단 1차 공부는, HyperSkill 에서 하기로 했다.

 

아름답지 않은가? 일단 모두 끝냈다.

간단히 정리도 했다.

 

자바를 주로 쓰다보니 자바를 중심으로 차이점을 찾게 되더라. 일단 재미는 있었다.

문제는 좀 쓸 데없이 귀찮았다. 굳이 이렇게까지 해야 하나 싶었다. (차라리 책을 볼걸)

 

 

변수

 

var 는 변하는, val 는 변하지 않는 변수를 선언할 때 쓰인다.

코틀린은 타입을 중요하게 생각하는 언어다. 타입 추론을 아주 잘 해주는 언어이기도 하다.

 

type

Bit width

Double

64

Float

32

Long

64

Int

32

Short

16

Byte

8

 

대충 사이즈는 위와 같다.

 

 

"Kotlin 에서 Character 는 Number 가 아니다."

자바는 primitive type, reference type 을 두고 있다. 그리고 확실히 구분해서 사용해야 한다.

하지만 코틀린은 그냥 모두 object로 바라볼 뿐이다.

 

 

String 

자바와 상당히 유사하다.

 

  • .first() returns the first symbol of the string.
  • .isEmpty() returns true, if the string has no symbols, otherwise, it returns false.
  • .drop(n) removes n first symbols from the string and returns the resulting string.
  • .reversed() returns the reversed string.
  • .toInt() converts the string to an integer and returns it.

등의 함수들을 제공한다.

자바는 charAt 등을 이용해 String 의 일부 '문자' 값을 읽을 수 있다.

 

코틀린의 String 에선 그냥 배열의 원소에 접근하듯이 접근하면 된다.

 

 

Val greeting = “Hello”

println(greeting.first())   // 'H'

println(greeting.last())    // 'o'

println(greeting.lastIndex) // 4

 

이런 것들도 기억 해두자.

 

코틀린에서 문자열과 숫자는 "불변" 이다. 그 중 문자열 같은 경우..

 

 

val str = "string"

str[3] = 'o' // an error here!

 

var str = "string"

str = "strong”//It’s ok

 

이런 특징을 갖고 있다.

 

중간 값만 못 바꾼다. 그냥 새로운 값을 만들어서 넣어야 한다. 이것이 바로 불변이란 것이다.

 

 

문자열 템플릿

 

  1. Use string templates to insert values of variables into a string like "this string has$value".
  2. If you would like to get an arbitrary expression - use curly braces like "The length is${str.length}".

이렇게 쓸 수 있다.

 

 

Range ( 범위 )

Kotlin 에서는

 

val within = a <= c && c <= b

요런 상황을 대신할

Ranges 라는 개념(?) 제공한다.

 

val within = c in a..b

 

이렇게, 그대로범위 지정하 ㄹ수 있다.

A~b 까지 모두 포함이다. 기억하자. 

 

val withinExclRight = c in a..b - 1 // a <= c && c < b

이렇게 하면 (b -1) 오른쪽 끝은 포함시키지 않는 범위를 만든다.

val range = 1..5 - 2

이렇게, 빼는 숫자를 늘릴수도 있다. 이러면 어찌되는가? 1..3 된다.

 

Not in 수도 있다.

 

val notWithin = 100 !in 10..99 // true

이렇게.

 

심지어 range integer에서만 있는게 아니라, character, String 에서도 있다.

 

println('b' in 'a'..'c') // true

println('k' in 'a'..'e') // false

 

println("hello" in "he".."hi") // true

println("abc" in "aab".."aac") // false

 

range 라는 놈은 어떤 object라고 생각하는게 편하다. 말이냐 하면,

Val range = a..b 

이런 식으로 range 객체를 변수에 할당할 수도 있다.

이렇게 하면

9 in range

이렇게 수도 있다.

 

 

 

Array ( 배열 )

특별한건 딱히 없다.

 

Kotlin provides many types for representing arrays: IntArray, LongArray, DoubleArray, FloatArray, CharArray, ShortArray, ByteArray, BooleanArray. Each array store elements of the corresponding type (Int, Long, Double and so on). Note, there is no StringArray.

 

다만 위와 같이,

타입별로 만들수 있는 Array 있다. String 제외한 기본 타입들은 전부 있다고 보면 된다.

 

 

val numbers = intArrayOf(1,2,3)

println(numbers.joinToString())

 

만약 Array 크기를 지정해서 만들고 싶다면?

 

val numbers = IntArray(5) 

이런식으로 하면 된다. 가장 문자가 대문자가 됐다.

요런 식으로 쓰면 된다.

 

println(array.first()) // "abc"

println(array.last()) // "efg"

println(array.lastIndex) // 2

 

위와 같은 편의 함수도 제공한다. ( String 과 유사해 보인다 )

 

값을 비교할 때는 == and !=  쓰면 안된다. (당연히)

 

만약 값이 같은지 비교하고 싶다면

 

println(numbers1.contentEquals(numbers2)) // true

println(numbers1.contentEquals(numbers3)) // false

 

 

 

Character ( 문자 )

 

코틀린은 문자를 숫자로 보진 않지만, 일관성은 어따 팔아먹었는지 ++ 같은건 또 지원한다. 이게 뭔 소리냐면.

 

val ch1 = ‘b’

ch1 + 1 // ‘c’

 

이게 된다는 말이다.

 

보통 문자는 ' ' 이렇게 따옴표 안에 한 글자 들어가는데...

 

val ch = '\u0040' // it represents '@'

println(ch) // @

 

요런 식으로 \u 를 붙여서 표현할 수도 있다. 헥사데시말 코드 로 나타내는 건데, 잘 모르겠다.

 

 

코틀린의 문자는 많은 멤버 함수를 갖고 있다.

 

 

  • isDigit() returns true if the given character represents a digit ('1''2', etc); otherwise, false;
  • isLetter() returns true if the given character represents a letter ('a''B''m', etc); otherwise, false;
  • isLetterOrDigit() returns true if the given character represents a letter or a digit; otherwise, false;
  • isWhitespace() returns true if the given character represents a whitespace (' ' or '\t'or '\n'); otherwise, false;
  • isUpperCase() returns true if the given character is an uppercase character; otherwise, false;
  • isLowerCase() returns true if the given character is a lowercase character; otherwise, false;
  • toUpperCase() returns the uppercase form of the given character;
  • toLowerCase() returns the lowercase form of the given character.

척봐도 쓸만해 보이는게 많다.

 

함수 (Function)

 

코틀린에서는 모든 함수는 "반환값" 을 갖는다. 정확히는 "반환 하는 것" 이 있다. void 같이, 아무것도 반환하지 않는다면??

 

val result = println("text")

println(result) // kotlin.Unit

This result is a special value called Unit, which means "no result".

 

항상 뭔가 뱉는다. 일단 아무것도 뱉는 같아도 kotlin.Unit 뱉음.

 

함수의 형식은 다음과 같다.

 

 

 

fun functionName(p1: Type1, p2: Type2, ...): ReturnType {

    // body

    return result

}

 

만약 한 줄로 표현할 수 있다면, curly braces 즉 중괄호는 생략 가능하다.

 

 

fun sayHello(): Unit = println("Hello")

 

Specifying the return type is optional, it can be inferred automatically:

fun sum(a: Int, b: Int) = a + b // Int

 

반환형은 안 써도 된다. (충분히 암시적이라면)

 

아, 함수의 argument 에 "기본 값" 을 설정할 수 있다.

 

default arguments allow programmers to create optional or special-case behaviour for functions.

 

fun findMax(n1: Int, n2: Int, absolute: Boolean = false): Int {

    val v1: Int

    val v2: Int

 

    if (absolute) {

        v1 = Math.abs(n1)

        v2 = Math.abs(n2)

    } else {

        v1 = n1

        v2 = n2

    }

 

    return if (v1 > v2) n1 else n2

}

 

 

 

 

val amount = calcEndDayAmount(ticketPrice = 10, soldTickets = 500, startAmount = 1000) 

 

이렇게 아규먼트 이름을 지정해서 수도 있고

 

이름 붙인거랑 붙인거랑 섞어서도 있는데

 

calcEndDayAmount(1000, ticketPrice = 10, soldTickets = 500) // 6000

 

섞어서 때는, 일단 이름으로 지정한 부터는 positional argument 없음.

 

 

 

Function 또한 일정한 타입으로 볼 수 있는데... ex) 3 -> Int , 3L -> Long

 

 

fun sum(a: Int, b: Int): Int = a + b

 

sum has a type of (Int, Int) -> Int.

 

fun sayHello() {

    println("Hello")

}

printHello has a type of () -> Unit 

 

이런식이다.

 

코틀린은 함수 또한 오브젝트처럼 다룰 수 있다.

 

Var mul = {a: Int, b:Int -> a + b}

이러면 mul 변수가 함수를 가리키는변수.

 

즉, 함수를 가리키는 "변수" 를 지정할 수 있다. 

 

mul 변수의 타입을 "명시적" 으로 표현해 볼까 그럼?

 

val mul: (Int, Int) -> Int = {a: Int, b: Int -> a + b}

 

요런식으로 표현이 된다.

 

그럼 함수를 mul 이라는 변수에 담았을 때는 저런 식으로, "참조" 할 수 있다 치고...

 

fun sum(a: Int, b:Int): Int = a + b

 

이렇게 이름이 부여된 함수를 넘기고 싶다면? 

 

fun sum(a: Int, b: Int): Int = a + b

val mul2 = { a: Int, b: Int -> a * b }

 

val increment = placeArgument(1, ::sum)

val triple = placeArgument(3, mul2)

 

:: 를 함수 이름 앞에 붙여서 넘기면 된다.

 

함수를 리턴하는 함수를 보면서, 함수의 타입에 대한 이해를 마치도록 하자.

 

 

 

fun getRealGrade(x: Double) = x

fun getGradeWithPenalty(x: Double) = x - 1

 

fun getScoringFunction(isCheater: Boolean): (Double) -> Double {

    if (isCheater) {

        return ::getGradeWithPenalty

    }

 

    return ::getRealGrade

}

 

 

이름이 없는 함수

 

이름이 없는 함수는 크게 두 가지로 나뉜다. 

 

하나는 익명, 하나는 람다.

 

  • fun(arguments): ReturnType { body } – this one is commonly called an "anonymous function".
  • { arguments -> body } – this one is commonly called a "lambda expression".

 

 

익명 함수가 이미 이름이 없는 함수인데 이게 뭔 개 소리인가 싶을 것이다. 그런데 어쩔 수없다. 영어 표현과 한국어 표현의 차이다.

영어로 표현하면 function which has no name. 요딴식이겠지.

 

하여간, 이름이 없는 함수는 => 어노니머스 함수 와 람다 함수. 이렇게 둘로 나뉜다.

(헷갈리니까 어노니머스 함수 라고 하자.)

 

fun(a: Int, b: Int): Int {

    return a * b

}

 

{ a: Int, b: Int -> a * b }

 

위의 두 표현은 "같은 표현" 이다.

 

 

val mul1 = fun(a: Int, b: Int): Int {

    return a * b

}

 

val mul2 = { a: Int, b: Int -> a * b }

 

이렇게 하면, 사실상 mul1 과 mul2 는 완전 똑같은 행위를 한다.

 

람다 함수의 경우, 매겨변수가 없을 때는

 

{ body }

 

요런 식으로 몸통만 써줘야 한다. -> 화살표는 반드시 생략한다.

 

람다를 매개변수로 받는 쪽은 여러 함축 단계를 거칠 수 있다. 매우 귀찮으니..

 

 

Lambdas and syntactic sugar

람다와, 시태틱 슈가

 

There are ways to make the code more readable for human without changing the code logic. If such a way is provided by the programming language and relates to syntax, the way is called syntactic sugar.

코드를 짜는 논리를 바꾸지 않으면서도, 코드를 좀 더 읽기 쉽게 하는 여러 방법이 있다. 만약 그런 것이 프로그래밍 언어 차원에서 지원될 때

우리는 이런걸 "syntactic sugar" 라고 부른다.

 

Kotlin promotes Functional Programming so there is syntactic sugar for it.

코틀린은 함수형 프로그래밍을 지향(?) 혹은 지원하며 이를 위한 문법적인 지원이 있다.

Let's recall the following example of passing the function as an argument:

 

fun isNotDot(c: Char): Boolean = c != '.'

val originalText = "I don't know... what to say..."

val textWithoutDots = originalText.filter(::isNotDot)


Rewrite it to pass a lambda:

 

val originalText = "I don't know... what to say..."

val textWithoutDots = originalText.filter({ c: Char -> c != '.' })

 

이런식으로 람다 함수를 쓰면, isNotDot 함수를 미리 선언할 필요가 없어진다.

 

Now we act! First of all, Kotlin infers types of many objects, and here specifying the c type isn't necessary:

originalText.filter({ c -> c != '.' })

 

그런데 솔직히 타입은 필요 없잖아? Char 를 굳이 써 줘야해? 생략하자.

 

Secondly, there are situations when the lambda is passed as the last argument. This is the case. Kotlin provides a way to eliminate these bracket sequences ({ }), allowing to write the lambda outside the parentheses:

originalText.filter() { c -> c != '.' }

 

그런데 함수의 매개변수로 넘어가는 람다가, "마지막 변수" 면, 사실 () 뒤쪽으로 빼내는게 좀더 보기 좋지 않냐? 그러니까 뺄 수 있어.

 

If the parentheses are left empty after this operation, they can be removed:

originalText.filter { c -> c != '.' }

 

아니 빼고 나니까 () 가 조금 거슬리네? 아무 변수도 없는데 저게 남아있잖아. 아 그럼, 아무것도 없는 괄호는 그냥 없앨 수 있게 하자.

 

() 안이 비어있으면 생략 가능함.

 

Finally, when there is a single parameter in a lambda, there is an opportunity to skip it. The parameter is available under the it name. The final version of the code removing dots is the following:

val originalText = "I don't know... what to say..."

val textWithoutDots = originalText.filter { it != '.' }

 

음... 다 좋은데. 저 c 가 마음에 안들어. 아니, 어차피 매개변수가 딱 하나인데... 굳이 c 요런 식으로 하나를 써 줘야해? 매개변수가 하나밖에 없을 때는 그냥 c 같은 건 생략할 수 있게 하는 건 어떨까?

 

람다는, 매개변수 없으면 -> 없어지잖아. 그 하나뿐인 매개변수는 it 으로 표현할 수 있게 하자..

 

 

 

결론:

람다를 바꿔 볼까? 코틀린은 형변환 해주니까, 람다 안의 매개변수 타입을 굳이 지정해 필요 없음.  그러니까 :Char 빼보자.

 

그런데 만약 람다가 마지막 아규먼트로 쓰인다? 그럼 () 오른쪽으로 있음.

그런데 왼쪽에 남은 () 안에 아무런 매개변수도 없잖아? 이걸 생략할 있어.

 

하지만 람다가 c -> c 이렇게 쓰는것도 별로인 같아.

왜냐면 매개변수가 하나밖에 없는데 굳이 -> 써야 할까?

 

이럴 때는 -> 빼고 it 있도록 했어. 짱이지?

 

 

.... 아주 그냥;;

 

Lambda 마지막 줄은 자동 return 이야. 마지막 줄에서 뱉는 값이 자동으로 return 된다는 말이지.

 

그런데 중간에 값을 뱉고 싶을수도 있잖아?

 

val textWithoutSmallDigits = originalText.filter {

    if (!it.isDigit()) {

        return@filter true

    }

        

    it.toString().toInt() >= 5

}

 

 

이런 식으로 있어

중간에 return 넣고, @ 마킹해줘야해

보통 @ 에다가 붙이는 이름은, 자기를 콜하는 함수 이름이야. (자기를 매개변수로 받는 )

 

lambda 물론 closure 개념을 갖고 있어.

 

클로저는 나중에 따로 정리하도록 하자.

 

일단 간단히..

 

클로저란?

MDN에서는 클로저를 다음과 같이 정의하고 있다.

클로저는 독립적인 (자유) 변수를 가리키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경을기억한다’.

흔히 함수 내에서 함수를 정의하고 사용하면 클로저라고 한다. 하지만 대개는 정의한 함수를 리턴하고 사용은 바깥에서 하게된다. 말로 설명하면 설명하기가 복잡하니 우선 코드를 보자.

 

 

function getClosure() {

  var text = 'variable 1';

  return function() {

    return text;

  };

}

 

var closure = getClosure();

console.log(closure()); //

 

 

자유 변수를 가리키는 함수. 클로저 안에 정의된 함수는 만들어진 환경 기억해.

여기서 getClousre 함수가 아니라, 안에서 뱉어지는 function() {return text; }

클로저야. 이 클로저는 말 그대로 "문을 닫는 느낌" 이지. text 배열을 자기 방 안에 넣고, 문을 닫아버리는 거야.

 

--

 

if 와 when

 

코틀린에서는

 

if 문이 , 아니라 표현이다.

 

표현은 반드시 반환값을 갖는 것이며, 문은 반환 값을 갖는다기 보다, 값들에 변화를 일으키는 

것들을 일컫는다.

 

만약 if 표현으로서 값을 반환하는 용도로 쓰인다면 반드시 else 있어야 한다.

 

 

또 switch 대신 when 이 있다.

 

When 또한 Expression 으로 있는데

때는 if 처럼 반드시 else 있어야 .

 

val result = when (op) {

    "+" -> a + b

    "-" -> a - b

    "*" -> a * b

    else -> "Unknown operator"

}

println(result)

 

보면, when(op)  이런 식으로 ( ) 안에 변수가 하나 들어가고

 

op 해당하는 값이 있으면 -> 분기를 타는 방식이다.

 

when (n) {

    0 -> println("n is zero")

    in 1..10 -> println("n is between 1 and 10 (inclusive)")

    in 25..30 -> println("n is between 25 and 30 (inclusive)")

    else -> println("n is outside a range")

}

 

 

만약 when 뒤에 아무런 변수도 없다? 그냥 모두 boolean 조건이 필요함.

 

    when {

        n == 0 -> println("n is zero")

        n in 100..200 -> println("n is between 100 and 200")

        n > 300 -> println("n is greater than 300")

        n < 0 -> println("n is negative")

        // else-branch is optional here

    }

이런 식으로...

 

 

Switch 다르게, 번에 분기만 있다. (여러 expression 실행 불가)

 

when(str) {

   “Hello”,”world” -> {

 

   }

}

이런 식으로는 쓸 수 있다. 이렇게 한 분기.

 

반복문

 

repeat(n) 이라는 함수가 있다. Argument int 값을 받아 n 실행한다.

 

While 문은 여타 while 문과 같음.

 

 scanner.hasNext() for strings and scanner.hasNextInt()

 

scanner hasNext()  를 활용할 수 있다.

 

라벨 개념

 

 

loop@ for (i in 1..3) { 

    for (j in 1..3) {

        println("i = $i, j = $j")   

        if (j == 3) break@loop  

    }  

}  

 

귀찮으니 간단히 정리하고 넘어가겠다.

 

val fileName = "src/reading.txt"

val lines = File(fileName).readText()

print(lines)

이렇게 가져오면, 파일의 모든 값을 한번에 가져옴.

 

메모리 제한은 2GB 정도다.

 

val fileName = "src/reading.txt"

val lines = File(fileName).readLines() 

for (line in lines){

    println(line)

} 

 

readLine 도 2GB. 사실상 전부 불러오고, List<String> 안에 한 줄씩 넣어놨을 뿐임.

 

readBytes() – may be helpful if you need to store file contents as an array of bytes:

이 것도, 결국 readText() 를 구현하기 위해 사용하는 세부 함수라서 2GB 메모리 제한임.

 

그 이상의 파일은 다음과 같은 방법을 사용해보라.

 

File(fileName).forEachLine { print(it) }

 

일단 넘어가자. 파일은 나중에 쓸 일이 있을 때 한번 더 훑어봐도 늦지 않는다.

 

 

 

클래스

 

Properties 반드시 초기화 돼야 .

 

Also, a property has a strict type. The type can be any. It can be a standard type like a number or a string or a custom type. So a property type can be your own class and even the same class where the property is declared.

 

 

 

 

Constructors are class members that initialize a new object of the class.

 

class Size {

    var width: Int = 0

    var height: Int = 0

 

    constructor(_width: Int, _height: Int) {

        width = _width

        height = _height

    }

}

 

이런 식의 생성자를 “Secondary constructor” 라고 한다. 차순위 생성자?

대체 생성자?

 

 

Omitting default values

Classes in Koltin have useful feature: you don't have to declare a default property value if the value is assigned in the constructor of the class:

 

 

 

 

Primary Constructor

생성자

존나 코틀린의 새로운 문법 하나인데

 

Class Size constructor(width: Int, height: Int) {}

 

요런 식으로 constructor 선언하는거임.

 

class Size constructor(width: Int, height: Int) {

    val width: Int = width

    val height: Int = height

    val area: Int = width * height

}

 

Primary constructor constructor 키워드는 생략이 되며,

심지어 primary constructor 에서는 변수 선언도 가능하다.

 

class Size(val width: Int, height: Int) {

    val height: Int = height

    val area: Int = width * height

}

 

위와 같이. Width 없던 변수를 선언 놓는 것이다. 

 

위의 클래스 선언은 사실상 번째 것과 다를게 없다.

 

 

class Size(val width: Int, val height: Int)

 

이런 식으로,  {} 생략하고 아주 간단한 Single line class 만들 수도 있다.

 

  • Any Kotlin class has a constructor to initialize its objects.
  • A constructor is available for invocation under the class name.
  • There are different ways to declare a constructor but a primary constructor is the most concise.
  • If a class has no custom constructors, then there is an implicit default constructor with no arguments and it does nothing.

 

 

모든 코틀린 클래스는 오브젝트를 초기화 하기위한 생성자를 갖고 있다.

컨스트럭트는 클래스 이름 아래에 있을 있다.

커스텀 컨스트럭터가 없다면, 기본 생성자가 암시적으로 존재한다.

 

 

enum class Rainbow(val color: String) {

    RED("Red"),

    ORANGE("Orange"),

    YELLOW("Yellow"),

    GREEN("Green"),

    BLUE("Blue"),

    INDIGO("Indigo"),

    VIOLET("Violet")

}

 

Enum 

 

enum class Rainbow(val color: String, val rgb: String) {

    RED("Red", "#FF0000"),

    ORANGE("Orange", "#FF7F00"),

    YELLOW("Yellow", "#FFFF00"),

    GREEN("Green", "#00FF00"),

    BLUE("Blue", "#0000FF"),

    INDIGO("Indigo", "#4B0082"),

    VIOLET("Violet", "#8B00FF");

 

    fun printFullInfo() {

        println("Color - $color, rgb - $rgb")

    }

}

 

 

Enum 기본 속성들

 

Name -> 그냥 이름 Rainbow.RED -> RED

Ordinal -> enum 순서?  Rainbow.GREEN.ordinal -> 3

Values ()-> enum instances 들을 반환.

 

fun isRainbow(color: String) : Boolean {

    for (enum in Rainbow.values()) {

        if (color.toUpperCase() == enum.name) return true

    }

    return false

}

 

반복문은 위와 같이 enum .

 

 valueOf() - returns an instance of Enum by its name with String type and case sensitivity

 

 

If you want to extend your Enum but with static context, then you need to wrap your method with companion object keywords, let's modify our Rainbow in order to find an instance by RGB parameter:

 

Companion object 여기서 처음 등장한다.

 

Static 으로 class member 추가할 사용한다.

 

enum class Rainbow(val color: String, val rgb: String) {

    RED("Red", "#FF0000"),

    ORANGE("Orange", "#FF7F00"),

    YELLOW("Yellow", "#FFFF00"),

    GREEN("Green", "#00FF00"),

    BLUE("Blue", "#0000FF"),

    INDIGO("Indigo", "#4B0082"),

    VIOLET("Violet", "#8B00FF"),

    NULL("", "");

 

    companion object {

        fun findByRgb(rgb: String): Rainbow {

            for (enum in Rainbow.values()) {

                if (rgb == enum.rgb) return enum

            }

            return NULL

        }

    }

 

    fun printFullInfo() {

        println("Color - $color, rgb - $rgb")

    }

}

 

이렇게 쓴다.

 

Member function 

 

자바에서는 클래스 안에 있는 함수를메서드라고 표현하곤 하는데,

여기서는 Member function 이라고 쓴다.

 

코틀린은 클래스에 function 확장 선언하는 기능을 제공한다.

 

이를 우린확장 함수” Extension Function 이라고 부른다.

 

fun String.repeated(): String = this + this

 

Fun 붙이고, “클래스”.”함수이름 하고내용을 선언하면 .

 

"ha".repeated() => “haha”

 

 

  • The syntax to define an extension function is like defining a top-level function. Just write the name of a class which you would like to extend and a dot before the function name. The class to be extended is called a receiver type.

, “클래스리시버 타입이라고 칭한다.

This 키워드를 사용하면, 확장 함수를 사용하는인스턴스 참조할 있다.

 

So the issue is solved: Kotlin developers are able to add any functions to any classes they want.

 

확장함수는 나름 안정성을 확보하기 위한 규칙을 갖고 있다.

일단, 확장함수 끼리는 중복이 안되며 (컴파일이 실패함), 이미 멤버 함수가 있을 , 확장함수가 이를 오버라이딩 없다.

 

 

fun product.takeFunction(productName: String): Product {

this.~~~()

this.~~~()

  return ~~~

}

 

 

 

 

블로그 이미지

맛간망고소바

,