728x90

 - 링크 : Marp for VS Code - Visual Studio Marketplace

 

Marp for VS Code - Visual Studio Marketplace

Extension for Visual Studio Code - Create slide deck written in Marp Markdown on VS Code

marketplace.visualstudio.com

마크다운을 ppt 양식으로 바꾸게 해주는 플러그인이다.

간단히 말해 일반 마크다운의 가로줄(---) 기능을 페이지 나누는 기능으로 쓰는 느낌.

마크다운을 이용한 타이핑 필기는 편하긴 하지만 개행 등을 잘 못하면 가독성이 극악이 된다는 단점이 있었는데,
이런식으로 PPT 양식으로 만들면 한 칸 내에 정보가 제한되는(?) 효과를 발휘하면서 굉장히 읽기 편한 자료를 만들 수 있었다.

다만 아직 개발중인 건지, 불완전한 모습이 간간히 보이고 있다. 어느 정도는 자동 맞춤을 해주지만, 글이 너무 많아지면 내용이 아예 잘려버린다던가(축소에 한계치가 있는걸까?) PPT 변환을 해봤더니 첫페이지 내용으로만 변환되는 문제도 있었고, 아쉽게도 이미지 파일 역시 첫 페이지만 변환이 가능하다. 어서 기능개선을 통해 불편한 점이 해결되었으면 좋을 듯.

728x90
728x90
SQL 문법 정리하기

SQL 문법 정리하기

  • SELECT : 테이블에서 데이터를 불러옴
    • 여러개를 불러올 수 있음
    • column명 뒤에 이름을 붙여 결과 table의 column 이름 겸 SQL문 내의 변수로 쓸 수 있음
    • *을 쓸 경우 table의 모든 변수를 불러옴
select (column name) from table
  • WHERE : 조건 부여
    • AND, OR, NOT을 이용해 여러개의 조건을 한번에 사용 가능
    • IN : 조건을 부여하는 COLUMN에서 여러 개의 값을 찾고 싶을 때 사용
      • where col is a or col is b or ... 대신
      • where col in (a,b, ...)
    • BETWEEN A AND B : column이 A와 B에 해당하는 범위를 갖는 경우
    • NULL : SQL 테이블의 NULL값은 별도로 탐색해주어야 함 / COUNT되지 않는 값으로 처리
    • LIKE : 문자열 패턴 검색
      • "%" : 와일드카드(임의 길이의 문자)
      • "_" : 1자리를 차지하는 문자
      • ex. where col like "_5%" : 2번째 글자가 5인 col 데이터
    • HAVING : WHERE 사용이 불가한 경우(COUNT 등의 집계함수에 사용)
  • DISTINCT : 중복 제거
  • JOIN : 두 테이블을 결함
    • INNER JOIN : 교집합
    • LEFT/RIGHT JOIN : 먼저/나중에 호출하는 테이블을 메인으로 집합
    • FULL OUTER JOIN : 합집합
[INNER/LEFT/RIGHT/FULL OUTER] JOIN table1 on table1.col == table2.col
  • MIN/MAX(col) : 해당 col의 최소/최댓값
  • LIMIT : 제한된 개수만 리턴
    • LIMIT n : n개 리턴
    • LIMIT a, n : a번째부터 n개만 리턴
  • GROUP BY col : col 기준으로 묶음
  • ORDER BY col [ASC/DESC] : col 기준으로 오름/내림차순 정렬
728x90
728x90
컬렉션의 구조와 list 사용

컬렉션의 구조와 list 사용

  • 컬렉션(Collection) : 자주 쓰이는 기초적인 자료구조를 모아둔 프레임워크
  • 코틀린의 컬렉션
    • list : listOf(불변형) / mutableListOf, arrayListOf(가변형)
    • set : setOf(불변형) / mutableSetOf, hashSetOf, linkedSetOf, sortedSetOf(가변형)
    • map : mapOf(불변형) / mutableMapOf, hashMapOf, linkedMapOf, sortedMapOf(가변형)
  • Collection의 특징
    • Iterable에서 확장
    • Collection에서 확장된 Set, List는 읽기 전용
  • collection 멤버
    • size : 크기
    • isEmpty() : 빈 컬렉션인 경우 true
    • contains(E) : 특정 요소(E)가 있다면 true
    • containsAll(collection) : 인자로 받아들인 Collection이 있다면 true
  • MutableIterable, MutableCollection 클래스
    • 요소를 추가, 제거 기능을 수행 가능
    • add(E) : 인자를 추가 후 true 반환 / 요소가 있거나 중복 불허인 경우 false
    • remove(E) : 인자를 삭제 후 true 반환 / 삭제 요소가 없으면 false
    • addAll, removeAll : 컬렉션 인자를 모두 추가/삭제
    • retainAll : 컬렉션 인자를 받아 해당 요소만 보유
    • clear() : 컬렉션 모든 요소를 삭제
  • List
    • 순서에 따라 정렬된 요소를 갖는 컬렉션
    • 불변형 리스트는 listOf()로 생성
    • 가변형 리스트는 mutableListOf(), arrayListOf()로 생성
    • 함수 인자는 vararg로 선언되어 있으므로 원하는 만큼 지정 가능

list 멤버와 이해

  • 코틀린의 가변형 리스트
    • arrayListOf
      • 가변형 List를 생성하나 자바의 ArrayList를 반환함
    • mutableListOf
      • 가변형 List를 생성하여 코틀린 MutableList를 반환
    • add()와 removeAt()으로 추가/삭제 가능
    • toMutableList()로 불변형 리스트를 가변형으로 변환 후 반환할 수 있음
  • List vs Array
    • Array 배열은 내부 구조상 고정된 크기를 갖게 됨
    • List의 경우 인터페이스로 설계되어 하위에서 특정 자료구조로 구현함
    • Array는 제네릭 관점에서 무변성, List는 공변성

Set, Map 컬렉션의 이해

  • Set
    • 정해진 순서가 없는 요소의 집합
    • 동일 요소가 중복되지 않음
  • hashSetOf
    • 자바의 HashSet을 만듬
    • 테이블에 요소를 저장 및 삭제 가능
    • hash table : 내부적인 키와 인덱스로 검색 및 변경을 빠르게 수행 가능
    • 정렬이 없지만 해쉬값으로 검색하므로 검색 속도는 O(1)의 시간 복잡도
  • sortedSetOf
    • 자바 TreeSet으로 반환
    • java.util.* 패키지를 임포트해야 함
    • 이진 탐색, Red-black 알고리즘을 이용
    • hash보다 추가/삭제 시간은 더 걸리나 검색/정렬이 뛰어남
  • linkedSetOf
    • 자바의 LinkedHashSet으로 반환
    • 연결 리스트 형태로 자료구조를 구성
    • 다른 Set보다 느리나 포인터 연결로 메모리 공간이 효율적으로 사용됨
  • Map
    • 키-값으로 연결된 요소 저장
    • 키는 중복 가능하나 값은 중복 불가
      • 기존 키와 동일한 경우 새로운 값으로 대체

컬렉션의 확장함수 - 연산, 집계, 검사

  • 코틀린 확장 함수 : 연산자, 집계, 검사, 필터, 변환을 제공
  • 컬렉션 연산자
    • +, - : 요소의 추가 혹은 제거 / 맵의 경우 일치하는 값
    • +/- ListOf : 리스트 병합 / listOf 원소와 일치하는 요소 제거
    • +Pair(값, 키) : Map 요소 추가
    • mapOf(값 to 키) : Map의 요소 추가
  • 요소의 집계
    • forEach(forEachIndexed) : 요소(+인덱스) 순회
    • onEach : 각 요소를 순환 후 컬렉션 반환
    • fold : 초기값 및 정해진 식에 따라 값 반환
      • reduce : 초기값 없이 정해진 식에 따라 값 반환
    • foldRight, reduceRight : 역순으로 동작하며 값 반환
//컬렉션 연산 fun main() { val list1 = listOf(1, 2, 3) val list2 = listOf("one", "two", "three") println(list1+ 4 ) //[1, 2, 3, 4], 산술 연산자로 새 원소가 합쳐진 새로운 리스트를 반환 } //컬렉션 fold val list = listOf(1, 2, 3, 4, 5) println(list.fold(4){total, next -> total+next}) //4+1+2+...+5 println(list.foldRight(3){total, next -> total+next}) //3+5+4+...+1 println(list.reduce{total, next -> total+next})//1+2+3+4+5

컬렉션의 확장함수 - 필터, 변환, 시퀀스

  • map() : 컬렉션 요소를 일괄적으로 식 적용 후 새 컬렉션 반환
fun main() { val list = listOf(1,2,3,4,5) println(list.map({it*2})) //[2, 4, 6, 8, 10], it은 리스트 원소를 가리킴 val mapIndex = list.mapIndexed{index, it -> index*it} //mapIndexed : 인덱스와 컬렉션 멤버로 연산 //[0, 2, 6, 12, 20] }
  • flatMap() : 각 요소에 식을 적용 후 새 컬렉션 반환
println(list.flatMap{listOf(it, 'A')}) //[1, A, 2, A, ...]
  • groupBy() : 요소를 그룹화한 후 Map으로 반환
  • 정렬 연산
    • reversed() : 역순
    • sorted() / sortedDescending() : 오름/내림차순 정렬
  • 시퀀스 : toList(), count()같은 연산에 의해 크기가 결정되는 특수 컬렉션
    • 지속적으로 내용이 추가되는 로그 파일 등
    • generateSequence(seed) {람다식} : 시퀀스 정의
    • take() : 원하는 요소 개수 획득
    • toList() : 시퀀스를 리스트 컬렉션으로 반환
728x90
728x90
제네릭의 기본 사용

제네릭의 기본 사용

  • 제네릭 : 자료형을 다루는 메소드나 클래스를 컴파일 시점에서 검사하여 적절한 자료형을 선택
    • 앵글 브라켓(<>) 사이에 자료형을 선언
    • 자료형을 대표하는 형식 매개변수로 T를 사용
class Box(a : Int) //원래의 클래스 선언 /////////// class Box<T>(a:T) //제네릭 클래스 선언 - 모든 자료형을 받을 수 있음 fun main() { val box1 = Box(1) //Box<Int>로 초기화 val box2 = Box("kim") //Box<String>으로 초기화 }

제네릭 함수

  • 제네릭 함수 : 함수나 메소드 앞에 지정
fun <T> genericFun(arg : T) : T? { ... } //T는 순서대로 형식 매개변수, 매개변수 자료형, 반환 자료형 fun <K, V> genericFun(key : K, value : V) : Unit {...} //형식 매개변수가 여러개인 경우 //배열의 인덱스 찾기 fun <T> find(a:Array<T>, Target : T) : Int { for (i in a.indices) //a.indice : a의 인덱스 반환 (0..n) { if(a[i] == Target) return i } return -1 } fun main() { val arr1: Array<Int> = arrayOf(1,2,3,4) println(find(arr1, 2)) //1 반환됨 } //람다식을 이용한 반환형 연산식 결정 fun <T> add(a:T, b:T, op : (T,T)->T):T { return op(a,b) } fun main() { val result = add(2, 3, {a, b -> a+b}) //람다식으로 2+3 반환됨 println(result) //5 출력 }
  • 함수의 형식 매개변수 제한하기 : <T:자료형>으로 선언하여 제한 가능
    • 함수 호출 시 해당 자료형으로 선언해주어야 함(<자료형>) - 만족하지 않을 경우 오류 발생
  • 가변성
    • 형식 매개변수가 클래스 계층에 미치는 영향 정의
    • 상위 클래스가 하위 클래스를 수용할 수 있음
      • ex. Number(정수, 실수를 모두 포함) > Int, Int?(Nullable) > Int

가변성의 유형

  • 무변성 : C와 C<T'>는 무관
    • 코틀린에서는 별도 지정이 없으면 형식 매개변수는 무변성
  • 공변성 : T'이 T의 하위 자료형이면, C<T'>는 C의 하위 자료형
    • <Out T`>로 선언
    • 하위 자료형이 상위 자료형으로 캐스팅됨
  • 반공변성 : T'이 T의 하위 자료형이면, C<T'>는 C의 상위 자료형
    • <in T`>로 선언
    • 상위 자료형이 하위 자료형으로 캐스팅됨

자료형 프로텍션

  • 선언 지점 변성 : 클래스 자체에 가변성 지정 / 클래스 사용 시 자료형 지정 필요가 없음
  • 사용 지점 변성 : 클래스 생성 등 사용 위치에서 가변성을 지정
class Box<T>(var : item : T) { fun <T> printObj(box : Box<out Animal>) // Box를 사용할 때 가변성을 결정 { val obj : Animal = box.item //out이므로 getter가 동작 box.item = Animal() //out이므로 setter는 동작하지 않음 //자료형 프로텍션(out으로 선언)에 의해 안전성 보장 } }
  • 스타 프로젝션 : in/out 선언 없이 추후 겱정
    • <*>으로 선언
    • 자료형이 결정된 후에는 그 자료형만 사용 가능하도록 제한

배열

  • 데이터의 연속적 나열
    • arrayOf(), Array() 생성자로 생성
    • arrayOfNulls() : 빈 배열
    • 배열은 객체이므로 Heap에 저장됨
val numbers = arrayOf(1, 2, 3, 4) for (element in numbers) println(element)
  • 다차원 배열 : 배열의 배열
val array1 = arrayOf(1, 2, 3) val array2 = arrayOf(4, 5, 6) val array3 = arrayOf(7, 8, 9) val arr2d = arrayOf(array1, array2, array3) /* 1 2 3 4 5 6 7 8 9 */ //변수 선언 없이 2차원 배열 val arr2d = arrayOf(arrayOf(1, 2, 3), arrayOf(1, 2, 3), arrayOf(1, 2, 3)) /* 1 2 3 1 2 3 1 2 3 */
  • 자료형이 제한된 배열
    • arrayOf<자료형>(...)
    • charArrayOf(), booleanArrayOf(), ... 등 (자료형)ArrayOf()으로 작성
  • 배열 요소에 접근
    • 읽기
      • arr.get(인덱스) : 게터를 이용
      • arr[인덱스]
    • 쓰기
      • arr.set(인덱스, 값)
      • arr[인덱스] = 값
  • Array (요소 개수, 초기값) : 표현식을 이용한 배열 생성
    • 2씩 늘어나는 정수 배열 : Array(5, {i -> i*2}) (람다식으로 초기값 설정 가능)
    • 1000개의 null 배열 : arrayOfNulls(1000)
    • 1000개의 0배열 : Array(1000, {0})
  • 생성된 배열은 고정
    • 새롭게 할당 : arr.plus(요소)
    • 범위를 잘라내어 새 배열 생성 : arr.sliceArray(0..2)
  • 배열의 순환
    • forEach {element -> 식} : 요소별로 순환
    • forEachIndexed {i, e -> 식} : 인덱스, 요소를 배열에서 받아서 식 처리
    • Iterator 사용 : arr.iterator().next() (다음 index 반환)

배열의 정렬

  • 코틀린 Array는 기본적인 정렬을 제공
  • 정렬 배열 반환
    • sortArray() : 오름차순 정렬
    • sortArrayDescending() : 내림차순 정렬
  • 원본 배열 정렬
    • sort() : 오름차순
    • sortDescending() : 내림차순
  • 배열 필터링
    • filter(람다식) : 원하는 데이터를 선택 가능
    • minBy, maxBy, 필드보다 작은/큰 값
    • flatten : 다차원 배열을 평탄화

문자열의 기본

  • 문자열은 배열의 일종으로, 불변값으로 생성
    • 참조 메모리는 변경되지 않음
    • 새로운 문자열 대입 시 기존 문자열은 Garbage Collector에 의해 제거
  • 문자열 추출, 병합
    • String.substring(인덱스 범위) : 범위 내 문자를 String으로 반환
    • CharSequence.subSequence(인덱스 범위) : Charsequence로 반환
    • 병합 : 문자열은 덧셈을 통해 이어붙일 수 있음 ("ab"+"c" -> "abc")
  • 문자열 비교
    • a.compareTo(b) : a,b가 같으면 0, a가 작으면 양수, 그렇지 않으면 음수
      • 각 위치에 있는 문자열의 숫자값을 비교
    • a.compareTo(b, true) : 대소문자에 무관하게 비교
  • StringBuilder(문자열)
    • 문자열 공간을 더 크게 잡음
    • 작은 범위의 요소 변경이 용이 / 처리가 늦고, 변경이 없는 경우 메모리 낭비
    • 문자열 변경이 잦은 경우 사용
  • 그 외 메소드
    • append(문자열) : 문자열 뒤에 이어붙임
    • insert(인덱스, 문자열) : 해당 인덱스부터 문자열 이어붙임
    • delete(a, b) : [a, b-1]의 범위 문자 삭제
    • toLowerCase / toUpperCase : 소/대문자 변경
    • split(기준) : 기준 문자를 기준으로 한 문자열 분리
    • trim() : 앞뒤 공백 제거
728x90
728x90
추상 클래스 (abstract class)

추상 클래스 (abstract class)

  • 구현할 클래스의 명세를 정의 : 하위 클래스에서 구체 사항을 구현
    • 실제로 구현되지는 않음
    • ex. abstract class Vehicle : 하위 클래스로 차량의 클래스인 차량, 오토바이 등을 구현
    • open 키워드 없이 상속 가능
abstract class Vehicle(val name : String, val color : String, val weight : Double) //primary constructor 속 프로퍼티는 abstract가 아님 { abstract val maxSpd : Double //추상 프로퍼티 : 하위 클래스에서 override해야 함 abstract fun start() abstract fun stop() // 추상 메소드 : 하위 클래스에서 구현해야 함 fun display() { println("$name / $color / $weight") }//비 추상 메소드 : 하위 클래스 모두가 해당 구현물을 갖게 됨 } class Car(name : String, color : String, weight : Double, override val maxSpd : Double) : Vehicle(name, color, weight) //상속 선언(maxsPd override 포함) { override fun start() { println("car start") } override fun stop() { println("car stop") } }
  • object를 이용한 추상 메소드 구현
abstract class Printer { abstract fun print() } val myPrinter = object : Printer() { override fun print() println("출력!")//하위 클래스 선언 없이 임시로 추상 메소드 구현 가능 }

인터페이스

  • 해야 하는 작업에 대한 추상적 명세
    • 클래스가 아니므로 다중 상속 가능
    • 강한 연관을 갖지 않음
interface Pet //인터페이스 상속 시 ': 인터페이스명' 추가 { //abstract 없이도 프로퍼티/메소드 선언됨 var category : String fun feeding() //다만 메소드는 내용 작성 시 일반 메소드로 동작 fun patting() { println("Keep patting!") } } class Cat(override var category : String) : Pet { override fun feeding() { println("Feed cat tuna!") } //patting은 인터페이스에서 선언되었으므로 오버라이드가 없어도 됨 }

데이터 클래스

  • 데이터 전달을 위한 객체 DTO(Data Transfer Object)
    • 자바에서는 POJO(Plain Old Java Object)
    • 구현 없이 데이터를 표현
    • 데이터를 접근하는 게터/세터 포함
  • 코틀린의 데이터 클래스 : 프로퍼티 = 필드 + 게터, 세터
  • 자동 생성 메소드
    • 게터, 세터
    • 비교를 위한 equals(), 키를 위한 hashCode()
    • 프로퍼티를 문자열로 보여주는 toString()
    • 객체 복사를 위한 copy()
    • 프로퍼티에 상응하는 component1(), component2(), ...
  • 선언 방식 : data class 이름(프로퍼티)
    • 주 생성자는 최소 하나의 매개변수를 가져야 함
    • 주 생성자의 모든 매개변수는 val, var 프로퍼티여야 한다
    • 데이터 클래스는 abstract, open, sealed, inner 키워드를 쓸 수 없음
data class Customer(var name : String, var email : String) { var job : String = "unknown" constructor(name : String, email : String, __job : String) : this(name, email) { job = __job } // 부 생성자 : 프로퍼티 선언 init { // init : 간단한 로직 선언 가능 } } val cus1 = Customer("kim", "kim@mail.com") val cus2 = Customer("kim", "kim@mail.com") println(cus1 == cus2) //동등성 비교, true 반환 println(cus1.equals(cus2)) //위와 동일 println("${cus1.hashCode(), ${cus2.hashCode()}}") // 고유값 동일 - 두 객체의 값이 동일하므로 참조하는 위치도 동일함 val cus3 = cus1.copy(name = "alice") // cus1 내용을 복사하면서 name만 새 값을 대입
  • 디스트럭처링(destructuring) : 객체의 프로퍼티를 개별 변수로 분해
val (name, email) = cus1 val (_, email) = cus1 // 특정 프로퍼티가 필요 없는 경우 val name = cus1.component1() //cus1의 1번째 component(name) 반환 val customers = listOf(cus1, cus2) //DTO가 많은 경우 리스트화 후 반복문 사용 for((name, email) in customers)

내부 클래스와 중첩 클래스

  • 코틀린의 내부 클래스
    • 중첩(Nested) 클래스 : 객체 생성 없이 이용 가능
      • 외부 클래스 생성 없이 내부의 nested 객체를 생성할 수 있음
      • 외부 클래스에 companion object를 갖고 있을 경우 해당 객체에 접근 가능
    • 이너(inner) 클래스 : 필드, 메소드와 연동하는 클래스(inner 키워드 필요) - 외부 클래스 프로퍼티에 접근 가능
      • 클래스 내에 키워드 없이 선언 시 nested class로 선언됨, 내부 클래스는 외부에 접근이 불가능하게 됨
      • 바깥 클래스의 private 멤버도 접근 가능
    • *익명 객체 : 일회용 객체 선언을 위해 object 키워드 사용

지역 클래스와 익명 클래스

  • 지역 클래스(Local Class)
    • 특정 메서드 블록이나 init블록과 같이 그 안에서만 유효한 클래스
      • 블록 범위 내에서는 사용되지 않음
class Smartphone(val model:String) { fun powerOn() : String class Led(val color : String) { fun blink() : String = "Blink $color on $model" }//지역 클래스 - 외부 프로퍼티에 접근 가능 val powerStatus = Led("Red") return powerStatus.blink() }
  • 익명 클래스(Anonymous Class)
    • 일회적으로 객체를 생성해 사용
    • 메모리 효율 혹은 개발 속도(오버라이딩 구현) 면에서 사용

실드 클래스와 열거형 클래스

  • 실드(Sealed) 클래스
    • sealed 키워드를 사용
    • 그 자체로는 추상 키워드와 같이 객체 생성은 불가
    • 기본 생성자는 private, 그 외에는 불허
    • 같은 파일 내에서만 상속 가능
    • 블록 내의 클래스는 필요한 경우 open 키워드로 선언하여 상속 가능
    • 주로 상태의 정의와 관리에 사용
sealed class Result { open class Success(val message : String) : Result() //해당 클래스는 상속 가능 class Error(val code : Int, val message : String) : Result() } class Status : Result() // 같은 파일에서만 상속 가능 class Inside : Result.Success("Success") // 내부 클래스 상속
  • 열거형 클래스(enum class)
    • 여러 상수를 선언하고 조건에 따라 값을 선택 가능
    • 동일한 자료형의 상수 나열 가능
enum class 이름(생성자) { 상수1(값), 상수2(값), 상수3(값), ... //값은 선택 가능 }
  • 어노테이션 클래스
    • 코드에 부가정보 추가
    • @기호를 이용하여 사용
    • 컴파일러나 프로그램 실행 시 사전 처리
      • @Test : 유닛 테스트
      • @JvmStatic : 자바 코드에서 컴패니언 객체 접근
728x90
728x90
마크다운을 이용해 필기를 해보자

마크다운을 이용해 필기를 해보자

  • 연초에 마크다운의 존재를 처음 알고 쏠쏠히 써먹는 중이다.
  • 단순히 메모장으로 필기하는 것보다는 '조금' 더 상세하게 필기가 가능한데, 특히 코드 하이라이트나 VSCode extension을 이용한 이미지 붙여넣기 등의 기능 추가가 꽤 쏠쏠한 편이다.

  • 먼저 VScode를 설치한다. 다른 편집기도 많이 있긴 한데(StackEdit 등등...) 나는 이걸 쓰는게 다른 언어로 빨리 넘어가기도 좋고 해서 사용하는 편이다.
  • 설치할 익스텐션은 총 두개다 : Markdown All in One, Markdown Paste
  • 두 익스텐션까지 설치하고 나면, 이제 파일명.md로 파일 편집을 진행하면 된다.

간단한 마크다운 문법


#의 개수로 제목의 크기 조절이 가능하다(보통 2개까지가 유의미한 차이인듯)

# 1개

# 2개

# 3개

# 4개

#5개

-, +, *으로 글머리표를 쓸 수 있다.

  • 이렇게
  • 이렇게
  • 이렇게

숫자로도 순서가 있는 글머리표가 가능하다.

  1. 이렇게
  2. 이렇게
  3. 이렇게

-를 3번 쓰면 구분선이 생긴다


이렇게

`를 3번 쓰면 코드 하이라이트가 된다. 그 뒤에 언어 이름을 붙이면 해당 언어로 하이라이트가 된다.

//```c #include <stdio.h> int main(void) { printf("hello, world!"); }

꺽쇠 표시(>)를 쓰면 인용구로 사용할 수 있다.

이렇게

  • 달러 표시 사이에 있는 글들은 논문을 쓸 때 쓰는 tex 문법을 사용할 수 있다 : $$

    • 1, 12\sqrt1,\ \frac{1}{2}
  • 위에서 설치한 markdown paste는 복사한 이미지를 간단하게 붙여넣을 수 있다. ctrl+alt+v로 붙여넣으면 된다(다만 시간이 좀 걸릴 수 있다)

  • markdown all in one의 기능 중 md파일을 html로 바꾸는 기능이 있다. 이 기능을 이용하면 티스토리 글쓰기에 html 기능으로 작성한 글을 옮길 수 있다(테마에 따라 지원이 완전히 되지 않을 수 있다.)

  • 링크는 대괄호에 [표시할 이름]을, 소괄호에 (링크)를 넣는다. [ ] ( )이런 식으로(사이 공백은 붙인다.) : 이 글로 다시 돌아오는 링크

  • 이외에도 많은 문법이 있는데, 구글에 검색하면 많으나 컴퓨터로 기록할때는 이정도를 주로 쓰고 있다. 너무 악필이다 보니 컴퓨터 기록 방법을 고뇌하다 찾았는데, 생각보다 너무 유용하게 쓰이는 듯.

  • md 파일은 Github 웹사이트를 만들 때도 쓸 수 있는데, Github의 경우 티스토리보다 손이 좀 많이 가다 보니(웹사이트 구축에서 막히기 시작하니까 흥미가 훅 떨어지더라...) 그냥 티스토리에 아예 정착한 상황이다. md파일이 있으니 원할 때 그대로 옮겨갈 순 있을 것 같긴 한데, 티스토리가 섭종하지 않는 한은 그냥 이대로 갈 것 같다.

728x90
728x90
프로퍼티의 접근 - Setter, Getter

프로퍼티의 접근 - Setter, Getter

  • 자바의 필드 : 접근 메소드를 필요로 함
  • 코틀린의 프로퍼티 : 변수 선언 외에 접근 메소드가 별도로 있음
    • Getter/Setter : 코틀린의 프로퍼티 접근 메소드
class Person(var name: String, var age: Int) // 클래스 선언 fun main() { val user = User("Kim", 20) val name = user.name //getter에 의한 프로퍼티 반환 user.age = 25 //setter에 의한 프로퍼티 값 변경 }
  • 게터와 세터의 설정 원리 : 변수 설정 시 get(), set()이 각각 자동으로 선언됨
    • 아래 양식처럼 암묵적으로 선언되며 같은 양식대로 직접 커스텀할 수 있음
Class bar(...) { val A : Int //불변형은 getter만 선언됨 get() = field /* 프로퍼티를 get에 대입 시 무한 재귀 호출이 되기 때문에, 프로퍼티를 가리키는 변수인 field로 별도로 선언됨 */ var B : Int //가변형은 get, set 모두 선언됨 get() = field set(value) { field = value } }

지연 초기화

  • 클래스의 프로퍼티는 null일 수 없으므로 객체 생성 시 초기화가 필요한데, 객체 정보가 나중에 나타나는 경우 나중에 초기화할 방법이 필요
  • lateinit, lazy 키워드로 지연된 초기화 가능
  • lateinit
    • 클래스 간의 의존성이 있는 경우 (특정 클래스가 생성되어야 초기화할 수 있는 경우)
    • 테스트를 위해 임시로 객체를 생성해야 하는 경우
    • var형 프로퍼티만 가능
    • 초기화 전에는 프로퍼티의 getter, setter 사용이 불가
class Person { lateinit var name : String fun test() { if(~::name.isInitialized) println("not initialized") //초기화 여부 확인 else println("initialized") } } fun main() { val kildong = Person() kildong.test() //"not initialized" kildong.name() = "Kildong" //isInitialized = true kildong.test() //"initialized" } ///////////////////////////////////////////////////////// // lateinit을 이용한 클래스 생성의 지연 초기화 data class Person(var name : String, var age : Int) lateinit var person1 : Person //클래스 지연 초기화 fun main() { person1 = Person("Kildong", 30) //생성자 호출 시점에 초기화 }
  • lazy : 호출 시 by lazy로 지연 초기화
    • val에서만 사용 가능, 초기화 후값 변경 불가
    • lazy 키워드의 모드
      • by lazy(mode = SYNCHRONIZED) : 단일 스레드의 사용 보장
      • by lazy(mode = PUBLICATION) : 여러 곳에서 호출될 수 있으나 처음 초기화된 값 사용
      • by lazy(mode = NONE) : 락이 되지 않으므로 여러 스레드의 접근이 가능하나 값이 일관되지 않을 수 있음
class Lazytest { init {println("init block")} val subject by lazy { println("lazy init") "kotlin programming"//subject 접근 시 대입됨 } fun flow() { println("not init") println("subject : $subject") // 이 시점에서 subject가 초기화됨 } } fun main() { val test = Lazytest() test.flow() }
  • by를 이용한 위임
    • 람다식을 사용
    • 한 클래스가 다른 클래스에 위임
    • 위임된 클래스 멤버는 참조 없이 호출
    • <var|val|class> 이름 : 자료형 by 위임자
  • 위임을 쓰는 이유
    • 코틀린 라이브러리는 open되지 않은 클래스(상속 불가)
    • 표준 라이브러리의 복잡한 상속을 방지하나, 기능 확장이 어려움
    • 위임 사용 시 : 클래스 기능에 추가 기능을 구현 가능
interface Animal() { fun eat() {...} } class Cat = Animal() val cat = Cat() class Robot = Animal by cat //RobotCat의 멤버를 사용 가능
  • 위임의 특수 키워드
    • observable : 프로퍼티를 보다가 변경 발생 시 호출
    • vetoable : 반환값에 따른 변경 허용 및 취소
import kotlin.properties.Delegates class User { var name : String by Delegates.observable("NONAME")//observable 매개변수로 name 초기값 설정 { prop, old, new -> //프로퍼티, 기존값, 새로운 값을 매개로 받음 println("$old->$new") //이벤트 발생(name값의 변화) 시 실행 } }

정적 변수와 메서드

  • 코틀린의 클래스는 동적으로 생성
  • 동적 초기화 없이 사용 가능한 변수 = 정적 변수 : 코틀린에서는 컴패니언 객체라고 칭함
  • 사용하지 않아도 메모리에 상주하므로 자주 사용하는 객체에 대해 사용
class Person { var id : Int = 0 var name : String = "kim" companion object // 컴패니언 객체 : 객체 생성 없이 접근 가능 { var lang : String = "Kor" fun work() { println("working") } } } fun main() { println(Person.lang) //인스턴스 생성 없이 출력 가능 Person.lang = "Eng" //변경 가능 Person.work() //메소드 실행 가능 println(Person.name) //name은 companion이 아니므로 에러 }
728x90
728x90
클래스와 객체의 정의

클래스와 객체의 정의

  • 객체지향 : 절차 중심의 코드를 구조적으로 하고자 함
    • 구조적인 코드 구조를 클래스 / 객체를 이용하여 실제 세계와 비슷하게 작성
    • 객체와 그 관계를 표현하여 확장 - 재사용이 용이
  • 객체지향 용어
    • 추상화(abstraction) : 어떠한 내용을 개념화하는 작업 - 클래스의 기본 형식 구성
    • 인스턴스(Instance) : 클래스 객체 생성
    • 상속(Inheritance) : 부모 클래스의 내용을 자식 클래스로 물려받음
    • 다형성(polymorphism) : 하나의 이름으로 다양한 처리를 제공
    • 캡슐화(encapsulation) : 메소드 내용은 외부 사용자가 접근할 수 없게 함
    • 메시지 전송 : 객체 간의 데이터 교환
    • 연관 : 클래스 간의 관계
  • 언어 별 동의어(코틀린 : 그 외 언어들)
    • 클래스 : 분류, 범주
    • 프로퍼티(Property) : 속성(Attribute), 변수(Variable), 필드(Field), 데이터(Data)
    • 메서드(Method) : 함수(Function), 동작(Operation), 행동(Behavior)
    • 객체(Object) : 인스턴스(Instance)

클래스 생성자 (Constructor)

  • 클래스 생성 시 호출되는 함수
    • 객체 생성 시 필요한 값을 인자로 설정 가능
  • 주 생성자(Primary Constructor) : 클래스명과 함께 기재, 보통 constructor 키워드는 생략 가능
  • 부 생성자 (Secondary Constructor) : 클래스명 본문에 기재, 하나 이상의 부생성자를 정의 가능
class Bird { //프로퍼티 var name : String = "noname" var wing : Int //생성자 constructor(name:String, wing : Int) { this.name = name //생성자, 메소드에서 클래스 프로퍼티 참조 this.wing = wing } //메소드 fun fly() { println("Fly!") } } fun main() { val coco = Bird("coco", 2) coco.fly() }

상속(Inheritance)

  • 자식 클래스가 상위(부모) 클래스 내용을 계승
  • 상위 클래스의 프로퍼티와 메소드가 하위로 적용됨
  • open class (class명) : 클래스를 상속 가능한 상태로
    • class (클래스명) : (상위 클래스명) : 클래스 상속
    • 코틀린 클래스는 묵시적으로 Any 클래스로부터 상속됨
open class Bird(var name : String, var wing : Int) //pri. Constructor, 프로퍼티 선언한 상위 클래스 { fun fly() { println("Fly!") } } class Lark(name : String, wing : Int) : Bird() //클래스 상속 : 상위 클래스의 프로퍼티와 동일하게 Construct { fun singalong { print("sing together") } } class Parrot : Bird() { var language : String //만약 하위 클래스에 새 프로퍼티 추가 시 별도로 선언 constructor(name : String, wing : Int, language : String) : super(name, wing) //부생성자로 클래스 상속 시 super 키워드 사용 { this.language = "..." } fun speak() { println("hello?") } } fun main() { var lark = Lark("mylark", 2) var parrot = Parrot("myparrot", 2, "Eng") }

다형성(Polymorphism)

  • 같은 이름을 사용하지만 매개변수가 다른 함수
    • 하나의 이름으로 여러 기능 수행
    • static polymorphism : 컴파일 시점의 다형성, 메소드 오버로딩
    • dynamic polymorphism : 런타임 다형정, 메소드 오버라이딩
  • 오버라이딩
    • 기능을 바꾸어 재설계
    • ex. push() - 확인 / 취소 로 서로 다른 기능을 수행하게 할 수 있음
    • 클래스 상속과 같이 open으로 상위 메소드에 선언해주고, override로 상속
    • final override 사용 시 오버라이드를 선언한 클래스의 하위 클래스는 재정의 금지
  • 오버로딩
    • 같은 기능을 구현하지만 인자 수나 타입이 다름
    • ex. print("hello") (string), print(1)(int)와 같이 같은 출력이지만 받는 인자가 다름
fun add(x:Int):Int { return x+1 } fun add(x:Double) : Double { return x+1.0 //오버로딩 : 다른 type } fun add(x:Int, y:Int) : Int { return x+y //오버로딩 : 다른 인자 개수 }

super, this

  • super
    • 상위 클래스의 참조
    • super.프로퍼티, super.메소드(), super() : 프로퍼티, 메소드, 생성자 참조
  • this
    • 현재 클래스의 참조
    • this.프로퍼티, this.메소드, this() : 프로퍼티, 메소드, 생성자 참조
open class Person { //상위 클래스 constructor(firstName: String) { println("[Person] firstName: $firstName") } constructor(firstName: String, age: Int) { //생성자 오버로딩 println("[Person] firstName: $firstName, $age") } } class Developer: Person { //Person 클래스 상속 constructor(firstName: String): this(firstName, 10) { // Developer 클래스의 아래 constructor 접근 (age default로 10 대입) println("[Developer] $firstName") } constructor(firstName: String, age: Int): super(firstName, age) { // Developer Class의 상위 클래스인 Person Class의 생성자 접근 println("[Developer] $firstName, $age") } }
  • 외부 클래스 호출(@)
    • 클래스 내부의 클래스(inner class)에서 상위 클래스 호출 시 super@클래스명으로 호출한다.
  • 앵글브라켓(<>)
    • 클래스와 인터페이스 중복 사용 시 사용할 상위 클래스를 지정 가능
open class A { open fun f() = println("A class f") fun a() = println("A class a") } interface B { fun f() = println("B interface f") fun b() = println("B interface b") } class C : A(), B { override fun f() = println("C class f") fun testing() { f() //C클래스의 f b() //B 인터페이스의b super<A>.f() //A클래스의 f super<B>.f() //B클래스의 f } }

가시성 지시자와 캡슐화

  • 클래스를 작성할 때 클래스 외부로부터 접근을 차단하는 속성이나 기능
  • 가시성 지시자(visibility modifier)
    • private : 클래스 내부에서만 접근 가능
    • public : 접근 가능(기본값)
    • protected : 상속된 클래스만 접근 가능
    • internal : 같은 모듈 내에서만 접근 가능
    • 변수명, 함수명, 클래스명, 지시자 등에 붙을 수 있음
728x90
728x90
람다식과 고차함수 요약

강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611

람다식과 고차함수 요약

  • 람다식 : {인자 -> 본문}
val sum : (Int, Int) -> Int = {x, y -> x+y} val mul = {x:Int, y:Int -> x * y} val add : (Int) -> Int = {it + 1} //it은 전달받은 인자를 의미 (함수 인자가 하나인 경우)
  • 고차 함수 : 리턴값이나 인자가 함수인 함수
fun high(name : String, body : (Int)->Int) : Int { prinln("name : $name") val x=0 return body(x) } //함수 호출 val res1 = high("TxT", {x->inc(x+3)}) //인자로 전달되는함수 인자가 하나인 경우 : it으로 대체 가능 val res2 = high("TxT") {inc(it+3)} //매개변수가 없을 때 함수 이름만 사용 val res3 = high("TxT", ::inc) //inc는 람다식으로 변환됨 // 매개변수가 하나인 경우 + 람다식 전달 val res4 = high("TxT") {it+3}

클로저

  • 람다식 함수에서 외부 변수에 접근할 수 있는 방법
  • 외부 변수를 capture하여 사용
fun main() { val calc = Calc() var result = 0 // 외부의 변수 calc.addNum(2,3) { x, y -> result = x + y } // 클로저 println(result) // 값을 유지하여 5가 출력 } class Calc { fun addNum(a: Int, b: Int, add: (Int, Int) -> Unit) { // 람다식 add에는 반환값이 없음 add(a, b) } }

코틀린 표준 라이브러리

  • 코틀린 표준 함수는 확장 함수 형태의 람다식으로 제공
  • let() : 객체를 인자로 넘기고 결과값 반환
//main문 내 val score : Int?=32 // 기존 null검사 fun chkScore() { if (score != null) println("Score : $Score") } //let을 이용한 null검사 - null이면 {...}이 실행되지 않음 fun letChkScore() { score?.let{println("Score:$it)} }
  • also() : let은 결과값 반환, also는 함수에 전달한 객체를 반환
    • 함수 블록 {...}의 마지막 문장을 let은 결과로 반환
    • also를 사용 시 마지막 문장을 반환하지 않음 (=대입이 안됨)
var m=1 m = m.also{it+3} //m은 1 - 연산한 결과가 m에 대입되지 않음
  • apply(): also와 같이 객체를 전달하고 반환받음
    • also와 달리 확장 함수로 처리되므로 클래스 인자 접근 시 it을 사용하지 않아도 됨
val person = Person("", 0) //apply val result = person.apply { name = "James" age = 56 } //also val result = person.also { it.name = "James" it.age = 56 }
  • run() : 익명 함수 / 객체 호출 두가지로 활용
    • block 내용 수행 후 결과값을 반환
    • 조건부 메소드 사용 가능
    • apply와 다르게 객체에 접근하면서 함수 블록{...}의 마지막 결과가 실행됨
run { if (firstTimeView) introView else normalView }.show()
  • with() : 전달받은 객체를 처리
    • safe call(?.)이 없으므로 let과 함께 쓰임
supportActionBar?.let { with(it) { setDisplayHomeAsUpEnabled(true) setHomeAsUpIndicator(R.drawable.ic_clear_white) } }
  • use() : 객체 사용 후 호출한 객체를 닫아줌(close())
    • 파일을 사용할 때 유용
private fun readFirstLine() : String { BufferedReader(FileReader("text.txt")).use{ return it.readline() } }
728x90
728x90
조건문을 통한 분기 (1)

강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611

조건문을 통한 분기 (1)

  • C언어의 조건식과 유사
if(...) { ... } else if (...) { ... } else { ... } val bar = if(...) a else b //1줄로 축약 가능 //if문을 이용한 대입 val a = 1 val b = 2 val bar = if(...) { println("a") a } else { println("b") b }
  • in 연산자 : 범위 내에 값이 있는지 확인
if (score >= 80 && score <= 89>) //score이 80 ~ 89 내인지? if (score in 80..89) { ... } // 위와 동일한 동작

조건문을 통한 분기 (2)

  • When문 : Switch - Case문의 간략화
when(x) { /*(일치하는 값 or 표현식) -> 수행할 명령문*/ 0, 1 -> printf("x is 0 or 1") returnvalue(x) -> print("return is correct") // 함수 리턴값과 비교 is Int -> println("x is int") /*(일치하는 범위) -> 수행할 명령문*/ in 1..10 -> println("x is in 1 ~ 10") !in 10..20 - > println("x is not in 10 ~ 20") ... /*else -> 수행할 명령문*/ else -> println("??") }
  • 인자가 없는 경우 - 다양한 조건식 구성 가능
var scroe = readline()!!.toDouble() var grade : Char = 'F' when { score >= 90.0 -> grade = 'A' score in 80.0..89.9 -> grade = 'B' score in 70.0..79.9 -> grade = 'C' else -> grade = 'F' } ...

반복문

  • for문
for(x in 1..5) // (요소 변수 in (컬렉션 or 범위)) { ... }
  • 다양한 반복법
//감소 for (i in 5 downto 1) //5,4,3,2,1 //단계별 증가 for (i in 1..5 step 2) //1, 3, 5 //혼합 for (i in 5 downto 1 step 2) //5, 3, 1
  • while문 : C의 while / do-while과 동일하게 동작한다.
while(...) { ... } //조건을 만족하는 동안 계속 동작 do { ... }while(...) //조건 검사가 밑에서 동작하므로 처음 1회는 무조건 동작

흐름의 중단과 반환 (1)

  • 흐름 제어
    • return : 함수의 결과를 반환
      • 반환값이 없는 경우 return 혹은 return Unit
      • 함수 마지막에는 Unit을 생략해도 return Unit이 동작함
    • break : 반복문을 끝냄
    • continue : 반복문 내용을 생략하고 조건으로 넘어감
  • 예외 처리
    • try {...} catch {...} : 예외 발생시 catch 내용 수행
    • try {...} catch {...} finally {...} : 예외가 발생해도 finally 내용은 수행

예외 처리

  • 실행 도중에 비정상적으로 프로그램 종료 시
    • OS 문제 (System Call Fault 등)
    • 입력값 문제 (int형에 문자열 입력 등)
    • 연선 문제 (divide by zero 등)
    • 메모리 할당 실패
    • HW 문제(전원 문제, 기억 장치 문제 등)
try { //예외처리 가능성이 있는 문장 } catch(e:classname) //e:예외처리 클래스 이름 { //예외처리 문장 } finally { //try-catch와 무관하게 실행할 문장 }
  • 사용자에 의한 예외 발생
    • throw Exception(message : String)을 이용
if(/* error */) { throw Exception("Error!") }
728x90

+ Recent posts