Programming58 코틀린(kotlin) - 변성: 제네릭과 하위 타입 변성(variance)은 List와 List )와 같이 기저 타입이 같고 타입 인자가 다른 여러 타입이 서로 어떤 관계가 있는지 설명하는 개념이다. 변성이 있는 이유: 인자를 함수에 넘기기 String 클래스는 Any를 확장하므로 Any 타입 값을 파라미터로 받는 함수에 String 값을 넘겨도 절대 안전하다. 하지만 Any와 String이 List 인터페이스의 타입 인자로 들어가는 경우에는 절대 안전하다고 말할 수 없다. 리스트의 내용을 출력하는 함수를 보자. fun printContents(list: List) { println(list.joinToString()) } >>> printContents(listOf("abc", "bac")) abc, bac 이 경우에는 각 원소를 Any로 취급하며 모든.. Programming/Kotlin 2021. 12. 12. 코틀린(kotlin) - 실행 시 제네릭스의 동작 소거된 타입 파라미터와 실체화된 타입 파라미터 JVM의 제네릭스는 보통 타입 소거(type erasure)를 사용해 구현된다. 이는 실행 시점에 제네릭 클래스의 인스턴스에 타입 인자 정보가 들어있지 않다는 뜻이다. 함수를 inline으로 만들면 타입 인자가 지워지지 않게 할 수 있다. 이를 코틀린에선 "실체화"라고 한다. 실행 시점의 제네릭: 타입 검사와 캐스트 자바와 마찬가지로 코틀린 제네릭 타입 인자 정보는 런타임에 지워진다. -> 제네릭 클래스 인스턴스가 그 인스턴스를 생성할 때 쓰인 타입 인자에 대한 정보를 유지하지 않는다. 예를 들어 List 객체를 만들고 그 안에 문자열을 여럿 넣더라도 실행 시점에는 그 객체를 오직 List로만 볼 수 있고, 어떤 타입의 원소를 저장하는지 알 수 없다.' va.. Programming/Kotlin 2021. 11. 27. 코틀린(Kotlin) - 제네릭 타입 파라미터 제네릭 타입 파라미터 제네릭스를 사용하면 타입 파라미터(type parameter)를 받는 타입을 정의할 수 있다. 제네릭 타입의 인스턴스를 만들려면 타입 파라미터를 구체적인 타입 인자(type argument)로 치환해야 한다. -> 만약 List 타입이 있을 때 그 안의 원소의 타입을 알 때, 타입 파라미터를 사용하면 "이 변수는 리스트이다." 가 아닌 "이 변수는 문자열을 담는 리스트이다."라고 할 수 있다. 코틀린 컴파일러는 보통 타입과 마찬가지로 타입 인자도 추론 가능하다. val authors = listOf("Dmitry", "Svetlana") listOf에 전달된 두 값이 문자열이기 때문에 컴파일러는 이 리스트가 List이라 추론한다. 빈 리스트를 만들 때는 타입 인자를 추론할 근거가 없.. Programming/Kotlin 2021. 11. 21. 코틀린(Kotlin) - 고차 함수 안에서 흐름 제어 람다 안의 return문: 람다를 둘러싼 함수로부터 반환 data class Person(val name: String, val age: Int) val people = listOf(Person("Alice", 29), Person("Bob", 31)) fun lookForAlice(people: List) { for(person in people) if(person.name = "Alice") { println("Found!") return } } println("Alice is not found") } >>> lookForAlie(people) Found! for문을 forEach 함수로 바꾸어도 루프의 기능은 동일하다. forEach에 넘긴 람다 안에 있는 return도 같은 의미이기 때문이다. f.. Programming/Kotlin 2021. 11. 14. 코틀린(Kotlin) - 인라인 함수 람다를 활용한 코드에선 무명 클래스 생성에 따른 부가 비용이 든다. 이 때문에 같은 작업을 수행하는 일반 함수를 사용한 구현보다 효율적이지 못하다. inline 변경자를 어떠한 함수에 붙이면 컴파일러는 그 함수를 호출하는 모든 문장을 함수 본문에 해당하는 바이트코드로 바꿔 일반 명령문과 같은 효율적인 코드를 생성하게 해 준다. 인라이닝이 작동하는 방식 위에서도 말했듯이 어떤 함수를 inline 선언하면 그 함수의 본문이 인라인 된다. 다른 말로 "함수를 호출하는 코드를 함수를 호출하는 바이트코드 대신 함수 본문을 번역한 바이트 코드로 컴파일하는 것이다." inline fun synchronized(lock: Lock, action: () -> T): T { lock.lock() try { return a.. Programming/Kotlin 2021. 11. 12. 코틀린(Kotlin) - 고차 함수 정의 고차 함수 정의 고차 함수는 다른 함수를 인자로 받거나 함수를 반환하는 함수이다. 코틀린은 람다나 함수 참조를 사용해 함수를 값으로 표현할 수 있으므로 고차 함수는 람다나 함수 참조를 인자로 넘길 수 있거나 함수 참조를 반환하는 함수인 것이다. ex) filter 함수는 술어 함수를 인자로 받으므로 고차 함수이다. list.filter(x > 0) 함수 타입 // 타입 추론 val sum = {x: Int, y: Int -> x + y} val action = { println(42) } // 함수 타입 선언 val sum: (Int, Int) -> Int = {x, y -> x + y} val action: () -> Unit = { println(42) } 함수 타입을 선언할 때는 반환 타입을 반드시.. Programming/Kotlin 2021. 11. 6. 코틀린(Kotlin) - 연산자 오버로딩과 기타 관례 어떤 클래스 안에 plus라는 이름의 특별한 메소드를 정의한다면 그 클래스의 인스턴스에 대해 + 연산자를 사용할 수 있다. 이런 식으로 어떤 언어 기능과 미리 정해진 이름의 함수를 연결해주는 기법을 코틀린에선 관례라고 한다. 코틀린에서는 언어 기능을 타입에 의존하는 자바와 달리 관례에 의존한다. 이는 기존 자바 클래스를 코틀린 언어에 적용하기 위해서이다. 기존 자바 클래스가 구현하는 인터페이스는 이미 고정돼 있고, 코틀린에서 자바 클래스가 새로운 인터페이스를 구현하게 만들 수 없다. 하지만 확장 함수를 사용하면 기존 클래스에 새로운 메소드를 추가할 수 있다. 따라서 기존 자바 코드를 바꾸지 않아도 새로운 기능을 쉽게 부여할 수 있게 된다. 산술 연산자 오버로딩 산술 연산자는 코틀린에서 관례를 사용하는 가.. Programming/Kotlin 2021. 10. 31. C언어 - 매크로와 선행처리기(preprocessor) 선행처리 선행처리는 컴파일 이전의 처리를 의미한다. 선행처리는 선행처리기에 의해, 컴파일은 컴파일러에 의해, 링크는 링커에 의해 진행이 된다. 컴파일 과정을 거치면 바이너리 데이터로 이뤄진 오브젝트 파일이 생성된다. 하지만 컴파일 이전에 진행되는 선행처리 과정을 거쳐 생성되는 파일은 그냥 소스파일이다. 선행처리기가 하는 일은 매우 단순한데, 삽입해 놓은 선행처리 명령문대로 소스코드의 일부를 수정한다. 여기서 수정이란, 단순 치환의 형태를 띠는 경우가 대부분이다. 선행처리 명령문은 # 키워드로 시작하며, 컴파일러가 아닌 선행처리기에 의해 처리되기 때문에 끝에 세미클론(;)을 붙일 필요가 없다. #define PI 3.14 위와 같은 명령문이 삽입돼 있는 소스파일을 선행처리의 과정에서 변환되는 것을 보자. .. Programming/C 2021. 10. 27. 코틀린(Kotlin) - 컬렉션과 배열 널 가능성과 컬렉션 컬렉션 안에 널 값을 넣을 수 있는지의 여부는 어떤 변수의 값이 널이 될 수 있는지 여부와 같이 중요하다. 컬렉션 타입 인자 뒤에 ?를 붙이면 널이 될 수 있는 값으로 이루어진 컬렉션을 만들 수 있다. fun readNumbers(reader: BufferedReader) : List { val result = ArrayList() for (line in reader.lineSequence()) { try { val number = line.toInt() result.add(number) } catch(e: NumberFormatException) { result.add(null) } } return result } 코드를 보면 2행에서 List를 볼 수 있다. List는 Int? 타.. Programming/Kotlin 2021. 10. 24. 코틀린(Kotlin) - 코틀린의 원시 타입 코틀린에서는 자바와 달리 원시 타입과 래퍼 타입을 구분하지 않는다. * 원시 타입 : 원시 타입의 변수에는 값이 직접 들어간다. * 참조 타입(reference type): 참조 타입의 변수에는 메모리 상의 객체 위치가 들어간다. 원시 타입 원시 타입은 참조 타입보다 값을 더 효율적으로 저장하고 이곳저곳으로 전달할 수 있다. 하지만 이 값에 대해 메소드를 호출하거나 컬렉션에 원시 타입 값을 담을 수는 없다. 자바에서는 참조 타입이 필요한 경우 특별한 래퍼 타입으로 원시 타입 값을 감싸 사용한다. 이 때문에 정수의 컬렉션을 정의하려면 Collection가 아닌 Collection를 사용해야 한다. 코틀린은 원시 타입과 참조 타입을 구분하지 않으므로 항상 같은 타입을 사용한다. val i: Int = 1 v.. Programming/Kotlin 2021. 10. 21. 코틀린(Kotlin) - 널(NULL) 가능성 자바에 비해 코틀린의 타입 시스템은 코드의 가독성을 향상하는 데 도움이 되는 몇 가지 특성을 제공한다. 대표적으로는 널이 될 수 있는 타입(nullalbe type), 읽기 전용 컬렉션, 배열지원이 있다. 널 가능성 널 가능성은 NPE오류(NullPointerException 오류)를 피할 수 있게 도와주는 코틀린 타입 시스템의 특성이다. 널이 될 수 있는지의 여부를 타입 시스템에 추가함으로써 컴파일러가 컴파일 시 오류를 미리 감지해서 실행 시점에 발생할 수 있는 예외 가능성을 줄일 수 있다. 널이 될 수 있는 타입 코틀린과 자바의 가장 중요한 차이는 코틀린 타입 시스템이 널이 될 수 있는 타입을 명시적으로 지원한다는 것이다. 자바에서 다음과 같은 코드가 있다 하자. int strLen(String s).. Programming/Kotlin 2021. 10. 20. C언어 - 메모리 관리와 메모리의 동적 할당 메모리의 구성 프로그램을 실행했을 때 운영체제에 의해 마련되는 메모리의 구조는 4개의 영역으로 나뉜다. 메모리 공간을 나눠놓은 이유는 유사한 성향의 데이터를 묶어 저장하면, 관리가 용이해지고 메모리의 접근 속도가 향상되기 때문이다. 메모리 영역별로 저장되는 데이터 유형 각 영역 별 특성에 대해 알아보면 다음과 같다. 1. 코드 영역 코드 영역에는 이름 그대로 실행할 프로그램의 코드가 저장되는 메모리 공간이다. CPU는 코드 영역에 저장된 명령문을 하나씩 가져가 실행을 한다. 2. 데이터 영역 데이터 영역에는 전역변수와 static으로 선언되는 static 변수가 할당된다. 이는 프로그램의 시작과 동시에 메모리 공간에 할당되어 프로그램이 종료될 때까지 남아있다는 특징이 있다. 3. 스택 영역 스택 영역에는.. Programming/C 2021. 10. 18. 이전 1 2 3 4 5 다음 728x90