youngseo's TECH blog

[KOTLIN] 객체지향 프로그래밍 문법 정리 본문

KAU

[KOTLIN] 객체지향 프로그래밍 문법 정리

jeonyoungseo 2022. 12. 12. 22:35

항공대학교 김철기 교수님 객프 수업을 정리한 내용입니다. 내가 나중에 보려고 쓴 거라 조금 난잡함 주의 🤐

<객체지향 프로그래밍 특징>

  • 자료 추상화가 가능하다.
    private
    등으로 불필요한 정보는 숨기고 중요한 정보만 노출할 있다.
  • 상속
    연관된
    클래스 간에 상하위 연관성을 있다.
  • 다형성
    오버라이딩
    override / 오버로딩 overloading 가능하다.

 

<KOTLIN 특징>

-안전성 : 타입추론 가능, Null Pointer Exception 예방, Smart Cast 통한 안전한 타입 변환 가능
-다중 패러다임 : 함수형 패러다임, 동시성 프로그래밍
-간결성, 표현력 좋음
-상호 운용성 / 다중 플랫폼

<변수>

  • 타입 추론이 가능하다.
    val n = 15
    굳이 val n : Int = 15 쓰지 않아도 된다.!
    val text = "apple"
  • 초기값 생략
    초기값 생략 시에는 무조건 TYPE 명시해야 한다.
    val n:Int
    , 변수에 값을 대입하지 않은 상태에서 연산 하면 안된다ㅠㅠ 컴파일 오류 발생
    (기존 프로그래밍의 경우 null 초기화를 해주지만 여기에서는 null pointer exception 원천적으로 차단한다.)

 

<연산자 우선순위>

  • 우선순위를 감안해서 해석해본다면??
    (a<b) == (b<c)
    (a==b) and (b==c)
    (a<(b or b))
    (a==b) || (b!=c)
    a=(b*c)

<기본타입>

Byte 1바이트 -128~127
Short 2바이트 -32678~32676
Int 4바이트 -2**31~2**31-1
Long 8바이트         -2**63 ~ 2**63-1
  • 표현방법
    val m =  332_856  //이건 Int인데 이런식으로 , _ 표현할 있다.
    val hundred1 =  100L // Long
    타입
  • 최솟값 최댓값 외우기 너무 어렵다면 출력해서 알아볼 있음
    Short.MIN_VALUE
    Int.MAX_VALUE
  • 부동소수점 Double (64비트) / Float(32비트)
    기본적으로 소수점 있는 수를 만들면 자동 Double이다. float 만들고 싶다면 3.14f 이런식으로!
  • Infinity 표현 가능
    100.0/0.0 = Infinity
    -100.0/0.0 = -Infinity
  • 문자 타입 Char
    val z = 'z'
    val pi = '/u03C0' //
    이건 특수문자
  • 수변환도 가능하다.
    945.toChar() //이러면 α가 자동으로 나옴
    (-2.45).toInt() //-2 반올림한 결과가 나온다. 그냥 toInt 소수부분을 삭제해준다고 생각하자.
  • 형변환은 자동으로 것으로 해주고, 자료형이 서로 다르다고 해도 크기 비교가 가능하다.
     

<비트 연산>

  • 일단 이거부터 알아두자!
    13: 000000001101
    -13: 111111110011
    그냥 (NOT 13) + 1 한다고 생각하자! -- 2의 보수법 참고

<비교와 동등성>

  • NaN 어떤 수와도 같지 않고, 어떤 수보다 크거나 작지 않다. 바보 같지??
    Double.NaN.isNaN
    True 가능하다!

<문자열>

  • Naming Convention
    변수명, 함수명은 camelCase 이용
    클래스이름은
    PascalCase 이용
    상수는
    전체를 대문자로 하는 snake_case 이용
  • 문자열은 배열이 아니다! String객체라고 생각해야 한다.
    \
    이스케이프 시퀀스를 이용하여 특수문자를 표현할 있다. 만약 \이스케이프 문자를 사용하고 싶다면 val message = """ Triple quote : '${"\"\"\""}' """ 이렇게!

<문자열 연산>

  • 문법
    "Hello".length
    "Hello".lastIndex

    "Hello".substring(2) //"llo"
    "Hello".startsWith("Hell") //true
    "abcabc".indexOf("ab") //
  • 문자열 + 숫자는 형변환이 자동으로 문자열로 된다!
    val str = "The sum is: " + sum
  • 문자열의 의미상 동등성 비교에는 "==" 또는 "!=" 사용하고, 동일 객체인지 비교할 시에는 "===" 또는 "!==" 사용

  • 문자열은 사전상 순서를 비교할 때도 사용 가능하다.
    print("abc" < "cba") //true


<
배열 Array!!>

val a = emptyArray<String>()
val b = arrayOf("hello", "world")
val c = arrayOf(1,4,'9') -> 이럴 경우 타입은 Any로 

람다함수로도 만들 있다.
val squares = Array(10) {(it + 1) * (it + 1)}

val operations = charArrayOf('+', '-', '*')

만약 배열을 똑같이 가져와 쓰고 싶다면, (공유없이)
val numbers = squares.copyOf() //copyOf
함수 사용!
copyOf(2)
라면 앞에서 2 원소만 배열 사본 생성

  • 타입이 정해지면 바꿀 없다!!
  • 배열을 생성하면 길이를 바꿀 없지만 + 연산자를 사용해서 원소를 추가한 '새로운' 배열을 생성할 있다.!
    val a = intArrayOf(1,3,4)
    val b = a+4 //
    이래도 4 넣어줌
  • 배열 비교
    '==' '!=' 연산자는 동일 객체인지 여부만 판단해준다. (여기가 String 다름)
    내용이
    같은지 판단할 때는 'contentEquals()'라는 함수 사용
  • 메소드 종류
    isEmpty
    isNotEmpty
    indexOf

<함수>

  • 파라미터의 타입은 항상 지정!
    fun circleArea(radius: Double): Double
  • 반환값의 타입을 생략할 있다.
    반환값이 없는 경우. : Unit 사실 타입 생략의 표시
    또는
    식에서 반환값의 타입이 너무 유추가능할 , 그냥 Double*Double 했다. 이럴 생략
  • 파라미터의 값은 수정이 불가능
    fun foo(bar: Int) : Int {
      val baz = bar+1
      return baz
    }
  • public 프로젝트의 어디서나 /internal 모듈  /private 같은 파일 안에서

<함수의 오버로딩>

  • 함수 이름은 똑같은데 매개변수만 다르게 함으로써 메서드를 여러 만드는 !

  • 함수 호출 오버로딩 해소 규칙

파라미터 개수와 타입을 기준으로 호출할 있는 모든 함수를 찾는다.
구체적인 함수를 제외시킨다. 어떤 함수의 파라미터의 타입이 다른 함수에 비하여 포괄적일 경우 이를 제외한다. 과정을 하나의 함수가 남을 때까지 반복

하나가 남으면 해당 함수 호출. 이상이 남으면 컴파일 에러 발생

같은   기능을   애초에   하지를   않음 ..

<패키지>

  • 동일 패키지의 함수는 import 없이 호출할 있다.
  • 다른 패키지의 함수를 호출할 때에는 함수의 이름에 패키지 이름까지 모두 붙여서 호출. 만약에 함수이름까지 붙이면 함수이름만으로 호출 가능
  • 다른패키지에 있는 동일한 이름의 함수 호출 둘다 함수까지 호출해야 하고 as 이름을 하나는 fooReadInt 하나는 barReadInt 이렇게 따로 지정해주자.
  • 전체 import (*사용) 가능하다. 구체적 import 비해 우선순위가 밀린다.

<조건문>

  • 만약 if문으로 값을 할당한다면 빠지는 있으면 안된다. if else까지 값이 들어갈 있도록 할당되어야

  • if 아직 끝났지만 return으로 함수 탈출 가능
  • when구문

  • for outerloop

 

<범위 타입>

  • 문자열 출력도 이런 식으로
  • until, downTo, step
    10 until 100 (10 .. 99
    같음)
    10 downTo 1 (10 .. 1
    같음)
  • 응용 가능
    "Hello World".substring(1..4)
    IntArray(10) {it * it}.sliceArray(2..5)

<클래스와 인스턴스>

  • 클래스 인스턴스를 만들 있다.
  • 클래스 생성자?
    기본생성자
    : 클래스를 만들 기본으로 선언 init  초기화 하려는데, 하나의 식으로 표현 어려울 . 반드시 모든 property 초기화되어야 한다.(클래스에 val/var로 정의되는 변수를 프로퍼티라고 한다.) *만약 주생성자를 바로 만들고 싶다면 그냥 파라미터에 val/var 붙이면
  • 보조생성자 : 필요에 따라 추가적으로 선언. 하나 이상의 생성자를 정의하고 싶을 . constructor(여기에 인자로 개만 가져갈 있음) ..

//this 생성자위임 호출이다.

  • 클래스에서의 멤버 가시성

public : 어디서나
internal : 모듈 안에서
protected : 멤버가 속한 클래스와 하위 클래스 --> 나중에 클래스 상속에서 !!
private : 멤버가 속한 클래스 내부에서만

무조건  Empty 안에서만   부를   수   있는  showMe

  • 추가_로컬 클래스라는 정의에 대해 알아두자.
    함수 내에서 class 정의할 경우 이를 지역 클래스라 부르고 함수에서 멤버에 접근 가능

 

<내포된NESTED 클래스와 내부INNER 클래스>

  • 중첩클래스는 외부 내용을 공유할 없지만, 내부 클래스는 외부 클래스의 속성과 함수의 사용이 가능하다.

<NULL>

  • ?. null safe operator  null이면 뒤에  let에서 사용      as?
  • ?: elvis operator  null이면 뒤에껄로 대체. 뒤에 return "Unknown" 이나 throw 두기도.
  • !!. non-null assertion operator  null이면 exception 발생.
  • 스마트 캐스트 - 프로그래머가 굳이 원하는 타입으로 캐스팅하지 않아도 컴파일러가 알아서 캐스팅해주는 의미 (원래는 논적으로 null 상황을 제일 먼저 제거해야 한다. )
    var 스마트캐스트 불가능.

<변수 초기화>

  • 늦은 초기화 : 변수에 객체에 할당하는 것을 선언과 동시에 없을 .
    lateinit var text: String  -- String
    기본 자료형에는 사용 불가, 초기값 할당 변수 사용X
    val a: Int by laxy{7} -- 실제 실행 시에는 var 변수를 '사용'하는 시점에 초기화 과정 진행.
    여러 개의 구문이 들어갈 있되, 마지막 값이 들어 .

<Property Field - 커스텀 접근자>

  • field가 뭐지..?
    프로퍼티가 가진 값이 저장되어 있는 곳이라고 생각하자. 메.모.리에 저장하는 형식이다.
    field는 언급을 해야지만 뒷받침하는 필드가 생긴다.

  • getter / setter
    property 의 데이터 얻거나 변경하기 위해 사용되며 접근자(accessor) 라 한다. get() set()으로 구현

<Object>

  • 생성자 없이 직접 객체를 만든다는 특징이 있다.
  • 하나로 공통적인 속성과 함수를 사용한다면!? Singleton Pattern!! 오직 하나의 인스턴스
  • 계산기
  • class 안에서도 object 만들 있다! companion object.
    다른 인스턴스인데 공통적으로 접근하는 또한 있도록 만들기

  • 객체식
    명시적인 선언 없이 객체를 바로 생성할 있는 특별한
    자바 익명 클래스와 비슷하다. 프로그램에서 일시적으로 한번만 사용되고 버려지며, 클래스 정의와 동시에 객체를 생성한다.
    가시적임!!

<고체함수>

  • 함수를 인스턴스처럼 사용

함수 타입 지정 방식은 위와 같다.

  • b안에 a함수 있지롱~

  • 람다를 사용한 중복 제거 (패러미터로 넘길 함수를 굳이 이름까지 만들어서 넘기지 않는다.
    함수의 형식을 적지 않고, 바로 중괄호 안에 parameter type 넣으면 알아서 추론해줌.
  • 컬렉션의 조작, 스코프 함수 사용에 도움
  • 반환값 앞에 : 아니고 ->
  • 반환값 없을 때는 -> Unit 반드시 명시
  • 프로그래머의 가시화를 위해 파라미터에 이름 붙이기 가능
    op: (firstValue: Int, nextValue:Int -> Int)
  • 람다함수의 마지막 문장의 식이 람다 함수의 결과값 !
  • 람다함수가 마지막 파라미터일 람다함수 바로 앞에서 괄호를 닫고 () {람다함수} 이렇게!
  • 파라미터가 없는 람다함수 -> 생략 가능
  • 파라미터 하나인 람다함수는 -> 이거 쓴다면, 파라미터 it으로 지칭
  • 사용하지 않는 파라미터 _, index 이런 식으로 _ 표현
  • 람다함수의 대안으로는 익명함수를 있는데
    res, elm -> res+elm

    fun(res, elm) = res+elm
  • 이미 add라는 함수가 존재한다면 ::add 넘기면 된다. :: 참조!

<확장함수 + 확장프로퍼티(getter,setter) +동반확장>

  • 기존에 정의된 클래스에 함수를 추가
  • util 많이 만듦
  • fun String?.truncate(maxLength:Int) = substring(0, maxLength)
    "HELLO".truncate(3)
  • 확장프로퍼티
    val IntRange.leftHalf: IntRange
        get() = start.. (start + endclusive) /2
  • 동반확장
    동반객체의 확장도 가능하다. 동반객체애 대한 확장 프로퍼티도 가능
    , 동반 객체가 존재하는 경우에만 동반 객체 확장이 가능(> Any 모든 타입의 최상위 타입이므로 동반확장이 불가능)

<영역함수>

  • 인스턴스의 속성이나 함수를 깔끔하게 불러 있다. + 람다함수!!
  • apply, run, with, also, let( 안전성 처리)
    apply 인스턴스 생성한 변수에 담기 전에 '초기화 과정' 수행할 많이 쓰임
    scope 안에서 참조연산자 없이 속성과 함수 사용 가능
    생성되자마자 조작된다면 인스턴스에 바로 넣어줄 있음
    also (it 통해 인스턴스 사용 - 같은 이름의 변수나 함수가 scope 밖에 있을 예방)
    run 일반 람다함수처럼 마지막 구문을 결과값을 반환
    이미 인스턴스가 만들어진 후에 인스턴스의 함수나 속성을 scope 내에서 사용해야 유용
    a.run { … }
    let (it 통해 인스턴스 사용)
    with run 동일. 단지 인스턴스를 참조연산자 대신 파라미터로 받음
    with(a) { … }

<하위클래스>

  • 형태  Apple : Fruit()
  • open class Fruit { ~
  • 하위클래스는 상위클래스 멤버 모두 상속
  • override 쓰려면 상위에 open class

-->

<상속>

  • 확장과 상속의 차이
    상속에서는
    인스턴스의 실제 타입(Apple? Fruit?)으로 호출 대상이 결정
    확장은
    변수의 타입에 따라 정적으로() 호출 대상이 결정
  • 상속 주의할
    상속한
    곳과 함수 형태(파라미터 , 타입 모두) 일치해야
    final 통해 추가 상속 제한 가능 final override fun start() {~ // 이미 상속 끝났다~
  • 프로퍼티(val, var 변수들) 상속
    하위
    클래스 본문에 구현을 넣어 상속 가능
    주생성자
    파라미터로 class Person(override val name: String): Entity() 이런 식으로 상속 가능
  • 불변 프로퍼티를 가변 프로퍼티로 상속 가능
    val -> override var
  • protected 접근 제어자
    상속에서
    강력하다. 상속해야만 있어.
  • 초기화의 순서는 어떻게 될까?
    상위 클래스 init 먼저, 다음 하위 클래스 init …
  • 상위 클래스 생성자로 데이터를 전달하고 싶다면?
    주생성자 속에서는 그냥 :상위클래스(파라미터에 전달)

부생성자에서는 일단 상위클래스 뒤에 () 이거 없애고 constructor(파라미터들): super(파라미터 ) { this.university = university }

  • 퀴즈 : 상위 클래스가 여러 생성자를 지원하고 하위 클래스에서도 상위 클래스의 여러 생성자를 이용하고 싶다면 어떻게 해야 할까?
    부생성자 여러 !!
  • this 누출 문제
    상속에서
    아직 하위 클래스가 초기화되지 않은 상태인데 상위 클래스에서 생성되면서 호출이 되는 문제
     

<타입캐스팅>

  • is, as
  • 컴파일 시간의 타입 검사
    컴파일
    시에는 변수의 타입에 맞추어 연산 검사를 수행한다. 1,"2" 있으면 *2 error
  • is Int -> ok. 자동 스마트 캐스트
  • as -> 강제 스마트 캐스트
    변환이
    불가능할 as 예외를, as? null 반환
     

<오버라이딩과 추상화-빈껍데기>

  • 오버라이딩 : super class에서 허용만 하면 서브클래스에서 형태의 함수 구현 가능
  • 추상클래스 : 직접 인스턴스화 없고, 다른 클래스의 상위 클래스 역할만! 있는 클래스. 선언부만 있고 기능 구현 X
  • 추상클래스의 생성자는 하위클래스의 위임 호출로만 호출 가능 super(name)
  • 추상 멤버에 대한 제약
    추상
    프로퍼티는 초기화할 없다.
    추상 함수에는 본문이 없다.
    추상 프로퍼티와 함수 모두 명시적 타입 / 반환 타입 필요하다. 타입 추론이 불가능하기 때문
    추상
    멤버는 기본적으로 open

<인터페이스>

  • 다중 상속 가능.
  • interface 다른 interface 상속 가능
  • 비추상 class interface 상속하면 interface 모든 추상 멤버 구현해야
  • 인터페이스의 함수나 프로퍼티는 구현 추가 가능. 구현을 했더라도 기본적으로 open~
  • 메모리관련 프로퍼티(상태, 생성자) val age = 0 , return field 이런 안됨
  • 다중상속 만약 같은 메소드가 된다면?
    반드시
    내부 구현이 존재해야 한다.

<Enum>

  • Custom Member

  • enum 클래스의 공통 멤버 (ordinal name)
    ordinal :
    상수의 순번  --> 그래서 < 이거는 ordinal 비교됨

name : 상수의 이름을 String 타입으로 반환

  • valueOf() values()
    name
    문자열로부터 상수를 얻어낼 valueOf() 함수 이용
    values() 모든 Enum 값이 들어있는 배열 반환해줌
  • sealed
    상속하는 하위 클래스의 정의를 같은 파일 내부로 제한. 함부로 상속하여 해당 class 완결성을 저해할 없도록!

<클래스 동등성 비교 너무 좋은 DATA CLASS>

  • equals / hashCode()
  • data 클래스
    toString() 자동으로 구현
    자동으로 동등성 체크
    copy() data class 복사

  • 구조 분해 가능. 구조 분해 선언의 일부 무시도 가능. for문에서 강력 key, value 느낌
     

<Pair Triple>

  • 선언 방법
    val pair = Pair(1,"Two")
    val pair =  1 to "Two"

<부호 정수 타입>

UByte / UShort / UInt / ULong

  • 부호 있는 타입과 타입변환 가능. range안에서 돈다고 생각.
    그런데 부호 있는 타입과 없는 타입 섞어서 연산은 안된다.

 

<컬렉션 타입>

  • 종류

ArrayList
List
MutableList
삽입 삭제 대치 가능
HashSet
TreeSet
Map / HashMap / TreeMap

  • 받을 때는 이렇게 받는다.

listOf()
sortedSetOf()
..

<파일과 I/O 스트림>

  • I/O 관련 클래스
    InputStream : Byte
    단위로 입력을 읽어온다.
    OutputStream: Byte
    단위로 출력을 쓴다.
    Reader :
    문자 단위로 입력을 읽어온다.
    Writer :
    문자 단위로 입력을 쓴다.

<객체지향 프로그래밍 키워드>

  • 객체는 별도의 역할이나 책임을 갖는 작은 독립
  • 유지보수, 확장성
  • 컴퓨터 프로그램을 명령어의 목록으로 보는 시각에서 벗어나 여러 개의 독립된 단위, 즉 "객체"들의 모임으로 파악하고자 하는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다.
  • 추상화 , 캡슐화 , 상속 , 다형성(오버로딩 오버라이딩)

<파일과 I/O Stream>

  • use
  • useLines -> 줄씩 읽는 sequence it으로 넘겨준다.
  • forEachLine -> 매번 읽은 줄을 람다함수 파라미터로

<제너릭>

  • 클래스나 함수에서 사용하는 자료형을 외부에서 지정
  • T,U,V 할당된 자료형으로 자동으로
  • 별도로 타입 패러미터에 자료형 전달할 필요 없다

'KAU' 카테고리의 다른 글

데이터베이스  (3) 2022.10.23
컴퓨터 구조론  (2) 2022.10.23
개발 블로그 시작  (0) 2022.05.21