Developing Myself Everyday
article thumbnail

변수와 상수


프로그램 언어 내에서 특정 값을 보관하는 장소는 변수와 상수입니다. 코틀린에서 변수를 정의할 때는 val, var을 사용할 수 있습니다. 상수는 const val 예약어만 사용할 수 있으며 정의할 수 있는 영역도 제한됩니다.

 


불변변수(val): 한번 저장하면 다시 할당할 수 없는 변수
가변변수(var): 재할당할 수 있는 변수
정의(Declaration): 변수와 상수를 처음으로 만드는 것
참조(Reference): 변수나 상수의 값을 이름으로 조회하는 것
할당(Assignment): 변수나 상수에 초깃값을 저장하는 것

 

변수와 상수를 정의할 때 사용되는 규칙이 존재합니다. 이는 다음과 같습니다.

 

  • 변수
    • 소문자나 언더스코어로 시작
    • 첫 문자에는 숫자를 쓰지 않는다.
    • 여러 단어를 연결해 표기할 때 두 번째 단어의 첫 글자를 대문자로 쓴다.
  • 상수
    • 패키지나 object에서만 정의가능
    • const val 예약어를 사용
    • 변수와 구별하기 위해 이름을 모두 대문자로 작성

 

변수나 상수의 식별자 이름을 작성하는 방법은 여러가지가 존재합니다.

 

카멜 표기법 (Camel Notation) - 카멜 표기법은 각 단어의 첫 글자는 소문자로 작성하고 나머지 단어들을 소문자로 작성하는 방식입니다. 예시 "camelCaseExample"

파스칼 표기법 (Pascal Case) - 파스칼 표기법은 카멜 표기법과 비슷하지만 첫 문자를 대문자로 작성합니다. 예시 "PascalCaseExample"

팟홀 표기법 (Pothole) / 스네이크 표기법 (Snake) - 각 단어를 밑줄(_)로 구분하는 방식입니다. 모든 문자는 소문자로 작성됩니다. 예시 "snake_case_example"

 

 

 

상수 변수 정의


이제 상수변수를 실제로 정의해보겠습니다.

 

상수 정의

상수를 정의할 때는  const val을 사용합니다. 

object Const {
	const val NAME = "준형"
}

 

변수 정의

변수를 정의할 때는 var이나 val을 사용합니다. 변수를 정의할 때는 해당하는 값의 자료형을 지정해야 합니다. 

val name: String = "준형" // 변수 선언과 초기값 할당 (불변변수)
var age: Int = 25 // 변수 선언과 초기값 할당 (가변변수)
age = 30 // 변수 값 변경

 

 

변수는 위치에 따라 2가지로 나눌 수 있습니다. 

 

지역변수 - 함수 안에서 정의해 사용하는 변수입니다. 지역변수는 외부에서 참조할 수 없습니다.

전역변수 - 지역변수 이외에서 정의된 변수입니다. 패키지 단위에 정의한 최상위 변수가 바로 지역변수입니다.

 

val PI = 3.14159 // 전역변수 PI 선언

fun calculateArea(radius: Double) {
    val area = PI * radius * radius // 지역변수 area 선언

    println("Area: $area") // area 값 출력
}

 

 

변수를 속성으로 사용

코틀린에서 실제 변수를 정의하면 게터와 세터 즉 변수를 참조하는 메서드를 내부적으로 제공합니다. 보통 속성은 클래스나 object 내부에 구현되며 객체가 만들어질 때 객체 영역에서 사용하는 상태를 만듭니다.

 

class Hello {
    val hello : String = "Hello" // 클래스 속성
}

object Const {
    const val NAME = "준형" // 객체 속성
}

fun main() {
    val hello = Hello() // 클래스 인스턴스 생성
    println(hello.hello) // 클래스 인스턴스로 속성에 접근
    println(Const.NAME) // 객체 이름으로 직접 접근
}

// 결과  
Hello
준형

 

위의 예제에서 볼 수 있듯이 클래스는 인스턴스를 가지고 속성을 참조할 수 있습니다. obejct는 하나의 객체만 만들므로 이름으로 직접 접근합니다.

 

 

 

변수 타입추론과 타입변환

위에서 변수를 정의할 때 해당하는 값의 자료형을 지정해야 한다고 했습니다. 다만 이는 매우 귀찮은 일입니다. 그래서 코틀린에서는 할당된 값인 객체를 보고 타입을 확정하는 타입추론(Type Inference)을 지원하고 있습니다. 할당된 값이 있다면 자료형을 지정하지 않아도 알아서 자료형을 지정해줍니다. 또한 변수에 정의된 자료형을 변경할 수도 있습니다. 이를 타입변환(Type Conversion)이라 합니다.

 

val age = 25 // Int 타입으로 추론됨
val name = "준형" // String 타입으로 추론됨
val pi = 3.14159 // Double 타입으로 추론됨

 

타입변환은 자료형 변환 메서드를 통해 할 수 있습니다.

val intNumber: Int = 42
val longNumber: Long = intNumber.toLong()

val doubleNumber: Double = 3.14
val floatNumber: Float = doubleNumber.toFloat()

val number: Int = 42
val numberString: String = number.toString()

 

위의 예제에서는 다른 타입의 변수를 할당할 수 있는 변수로 타입변환을 한 다음 다른 타입의 변수에 할당하고 있습니다.

 

다른 타입의 변수로 리터럴 표기법에서는 계산할 수 있습니다. 다만 값의 결과는 상위 자료형의 자료형으로 확정됩니다.

fun main() {
    val intNumber: Int = 42
    val doubleNumber: Double = 3.14

    val result = intNumber + doubleNumber

    println(result)
    println(result.javaClass)
}

// 결과
45.14
double

 

자료형 변환 메서드와 이에 대한 설명

자료형 변환 메서드 설명
toByte() Byte 타입으로 변환
toShort() Short 타입으로 변환
toInt() Int 타입으로 변환
toLong() Long 타입으로 변환
toFloat() Float 타입으로 변환
toDouble() Double 타입으로 변환
toChar() Char 타입으로 변환
toString() String 타입으로 변환
toBoolean() Boolean 타입으로 변환
toCharArray() 문자열을 CharArray로 변환
toUpperCase() 대문자로 변환
toLowerCase() 소문자로 변환

 

 

계산 연산자


연산자

연산자에 대해서 더 자세하게 알아보겠습니다. 연산자는 크게 2개로 나눌 수 있습니다.

 

단항연산자(Unary) - 항이 하나인 하나의 변수에서만 작동하는 연산자

이항연산자(Binary) - 두 변수의 값으로 작동하는 연산자

 

아래는 연산자와 메서드를 나타낸 표입니다.

표현식 메서드 이름 내부적 실행
a + b plus a.plus(b)
a - b minus a.minus(b)
a * b times a.times(b)
a / b div a.div(b)
a % b rem/mod a.rem(b), a.mod(b)

 

 

실제로 연산자의 내부가 어떤 메서드로 실행되는지 확인할 수 있습니다.

 

 

'+' 연산자는 plus() 메서드에 의해 처리되고 있다는 것을 알 수 있습니다.

 

 

아래는 연산자와 메서드를 각각 사용한 예시입니다.

fun main() {
    println(100 + 100)		// Output: 200
    println(100.plus(100))	// Output: 200

    println(100 - 100)		// Output: 0
    println(100.minus(100))	// Output: 0

    println(200 / 100)		// Output: 2
    println(200.div(100))	// Output: 2

    println(100 % 7)	// Output: 2
    println(100.rem(7))	// Output: 2

    println(10 * 20)		// Output: 200
    println(10.times(20))	// Output: 200
}

 

 

할당 복합 연산자

연산자로 연산한 결과를 동일한 변수에 할당할 경우 할당복합연산자를 사용할 수 있습니다.

기존 표현식 축약형 내부적 실행
a = a + b a += b a.plusAssign(b)
a = a - b a -= b a.minusAssign(b)
a = a * b a *= b a.timesAssign(b)
a = a / b a /= b a.divAssign(b)
a = a % b a %= b a.modAssign(b)

 

아래는 할당 복합 연산자를 사용한 예시입니다.

fun main() {
    var num = 100

    num += 100 // num = num + 100
    println(num) // Output: 200

    num -= 50 // num = num - 50
    println(num) // Output: 150

    num *= 2 // num = num * 2
    println(num) // Output: 300

    num /= 3 // num = num / 3
    println(num) // Output: 100

    num %= 7 // num = num % 7
    println(num) // Output: 2
}

 

 

단항 연산자

단항 연산자에는 증감 연산자와 부호 연산자가 있습니다. 아래는 단항 연산자를 나타낸 표입니다.

연산자 의미 표현식 내부적 실행
+ 양수 +a a.unaryPlus()
- 음수 -a a.unaryMinus()
! 부정 !a a.not()
++ 증감연산 ++a a.inc()
-- 감소연산 --a a.dec()

 

아래는 단항 연산자를 사용한 예시입니다.

fun main() {
    var num = 100

    num = +num // 양수 유지 (변경 없음)
    println(num) // Output: 100

    num = -num // 부호 반전
    println(num) // Output: -100

    num++ // 후위 증가 (num = num + 1)
    println(num) // Output: -99

    num-- // 후위 감소 (num = num - 1)
    println(num) // Output: -100
    
    var bool = true
    bool = !bool // 논리 NOT 연산 (true는 false로, false는 true로 변환)
    println(bool) // Output: false
}

 

 

연산자 오버로딩

문자열 등에도 덧셈연산자를 사용할 수 있습니다. 문자열에서의 덧셈연산자는 문자열을 결합하는 용도로 사용합니다.

 

val name = "준형"
val age = "26"
val result = name + age
println(result) // Output: 준형26

 

리스트에도 덧셈연산자를 사용할 수 있습니다. 리스트에서 덧셈연산자를 사용하면 리스트의 원소를 추가하거나 제거할 수 있습니다.

fun main() {
    val num = listOf(1, 2, 3, 4, 5)
    val num2 = num + 6
    val num3 = num2 - listOf(1, 2, 3)
    println(num3) // Output: [4, 5, 6]
}

 

 

이진연산자

이진 연산은 아래와 같은 메서드를 통해 처리할 수 있습니다.

표현식 설명
shl(a) 이진수를 왼쪽 시프트 연산
shr(a) 이진수를 오른쪽 시프트 연산
ushr(a) 부호 없는 이진수를 오른쪽으로 이동
and 비트 단위의 논리곱 연산
or 비트 단위의 논리합 연산
xor 비트 단위의 배타적 논리합 연산
inv(a) 비트를 반전시키는 연산

 

아래는 비트 연산자를 사용한 비트 연산의 예시입니다.

fun main() {
    val num1 = 0b1100 // 12 (이진수)
    val num2 = 0b1010 // 10 (이진수)

    // 비트 AND 연산 (&)
    val resultAnd = num1 and num2
    println("Bitwise AND: $resultAnd") // Output: Bitwise AND: 8 (0b1000)

    // 비트 OR 연산 (|)
    val resultOr = num1 or num2
    println("Bitwise OR: $resultOr") // Output: Bitwise OR: 14 (0b1110)

    // 비트 XOR 연산 (^)
    val resultXor = num1 xor num2
    println("Bitwise XOR: $resultXor") // Output: Bitwise XOR: 6 (0b0110)

    // 비트 NOT 연산 (inv())
    val resultNotNum1 = num1.inv()
    println("Bitwise NOT of num1: $resultNotNum1") // Output: Bitwise NOT of num1: -13 (-0b1101)

    // 비트 왼쪽 시프트 연산 (shl)
    val leftShiftedNum1 = num1 shl 2
    println("Bitwise Left Shift of num1: $leftShiftedNum1") // Output: Bitwise Left Shift of num1: 48 (0b110000)

    // 비트 오른쪽 시프트 연산 (shr)
    val rightShiftedNum2 = num2 shr 1
    println("Bitwise Right Shift of num2: $rightShiftedNum2") // Output: Bitwise Right Shift of num2: 5 (0b101)
}

 

만약 비트 연산의 결과물을 2진수로 출력하려면  'toString(2)' 을 사용하면 됩니다.

 

 

 

식별자


패키지

코틀린에서는 패키지를 사용해서 클래스와 함수 등을 그룹화하여 코드를 보다 구조적으로 관리할 수 있게 합니다. 

 

최상위 수준의 패키지에 속하는 클래스와 함수들은 따로 패키지를 선언하지 않더라도 사용할 수 있습니다.

 

fun main() {
    println("Hello, World!")
}

 

다만 다른 패키지에 선언된 클래스, 함수, 상수 등을 현재 파일에서 사용하려면 해당 요소를 가져와야 합니다. 이때 `import` 문을 사용해 해당 패키지를 명시적으로 지정하여 해당 패키지 내의 요소를 직접 참조할 수 있습니다.

 

`kotlin.math` 의 패키지에 들어있는 함수를 사용한 예시를 들어보겠습니다.

import kotlin.math.max

fun main() {
    val num1 = 20
    val num2 = 30
    // val maxValue = kotlin.math.max(num1, num2)
    val maxValue = max(num1, num2)
    println("$num1 과 $num2 중 가장 큰 값은 $maxValue 입니다")
    // Output: 20 과 30 중 가장 큰 값은 30 입니다
}

 

`*`를 사용한다면 해당 패키지 내에 있는 모든 함수를 사용할 수 있습니다.

import kotlin.math.*

fun main() {
    val num1 = 20
    val num2 = 30
    // val maxValue = kotlin.math.max(num1, num2)
    val maxValue = max(num1, num2)
    val minValue = min(num1, num2)
    println("$num1 과 $num2 중 가장 큰 값은 $maxValue 입니다")
    // Output: 20 과 30 중 가장 큰 값은 30 입니다
    println("$num1 과 $num2 중 가장 작은 값은 $minValue 입니다")
    // Output: 20 과 30 중 가장 작은 값은 20 입니다
}

 

`as`를 사용한다면 사용할 상수와 함수에 별칭을 부여할 수 있습니다.

import kotlin.math.max as maxOfNum

fun main() {
    val num1 = 20
    val num2 = 30
    val maxValue = maxOfNum(num1, num2)
    println("$num1 과 $num2 중 가장 큰 값은 $maxValue 입니다")
    // Output: 20 과 30 중 가장 큰 값은 30 입니다
}

 

 

식별자 구분

식별자란 변수, 함수, 클래스, 모듈 등의 이름을 지정하는데 사용되는 이름입니다. 식별자로 사용할 수 없거나 제약이 있는 예약어라는 것이 존재합니다.  예약어는 이미 특정한 의미와 기능이 할당되어 있는 단어를 말합니다.

 

 

표준 입출력

코틀린에서 표준 입출력은 kotlin 표준 라이브러리의 `readLine()` 함수와 `println()` 함수를 사용해 수행할 수 있습니다.

fun main() {
    print("Enter your name: ")
    val name = readLine()
    println("Hello, $name!")
}

'스터디 > 코틀린 언어' 카테고리의 다른 글

[Kotlin] 클래스 (2) - week 5  (0) 2023.08.08
[Kotlin] 클래스 (1) - week 5  (0) 2023.08.07
[Kotlin] 함수 알아보기 - week 4  (0) 2023.08.03
[Kotlin] 문장 제어처리 - week 3  (0) 2023.07.21
[Kotlin] 객체란? - week 2 (1)  (0) 2023.07.17
profile

Developing Myself Everyday

@배준형

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!