유니코드 캐릭터 셋 (UCS): 문자 표, UCS-2/4로 16/32 bits 테이블
UTF-8: 유니코드 문자열을 효율적으로 표현하기 위한 인코딩
인코딩이 없을 경우, 기존 ASCII 테이블은 7 bits로 표현 가능한데 굳이 2/4 bytes 공간이 필요함
예외처리 문자: 당연해서 생략. 특이사항은 ' 이게 변수 수명을 나타내는 표기라서 추가됨
" 으로 감싼 범위 내에 개행이 존재하면 그대로 반영됨. 이를 원하지 않는다면 개행 전에 \ 작성
예외 처리 문자가 너무 많아서 더러워 질 것 같다 → r#" 으로 시작해서 "# 으로 끝내면 됨
외부 텍스트를 변수로 긁어오고 싶다면 include_str! 매크로를 활용할 것
문자열 슬라이스: 문자열이 저장된 배열 중간을 deref 해서 추가 메모리 없이 표현. utf-8 경계에 걸치면 안됨
char: 유니코드 글자를 표현하기 위한 자료형. 4byte
String : 동적으로 변경 가능한, heap에 보관되는 문자열에 대한 struct
함수의 매기변수로 문자열 전달 시 문자열 슬라이스로 전달 → 소유권을 넘기지 않는다.
(slice, 소유권 관련해서 좀 더 봐야할거같은데)
.concat() : 문자열 배열을 바로 연결
.join() : 문자열 배열 사이에 특정 값을 넣어서 연결
format!() : sprintf
문자열 아닌 타입 → 문자열 변환 시 .to_string() 사용. 실패할수도 있어서 Result 로 리턴
객체지향 특징: 추상화 / 캡슐화, 다형성, 상속
(참고로 상속은 요새 객체지향 트렌드가 아님. 실제 상속보단 합성을 통한 구현이 트렌드)
Rust는 OOP가 아니다 / Golang도 비슷한 처지인데 지들은 OOP하게 짤 수 있다고 우기고 있다.
객체 타입 선언: struct 로 객체 멤버 변수 정의
객체 메서드 정의: impl Type 안에 fn method_name(&self) -> Ret 식으로 메서드 정의
self 는 C++/Java의 this pointer, python의 self (원조 맛집은 self임)
참고로 한번에 모든 메서드를 정의하지 않아도 됨. (어쩌면 다른 모듈에서 사용하면서 추가할수도 있을듯?)
현재 모듈에서는 모든 멤버 변수, 메서드에 접근 가능함
외부 모듈에서 접근 가능하게 하려면 pub 키워드 필요
trait : 인터페이스와 같이 구현해야 할 메서드 목록을 정의
해당 trait의 메서드를 구현한다면, 해당 struct는 주어진 trait로 casting 가능한 셈
trait 내부에 메서드 정의는 인터페이스만 하면 abstract, 구현까지 정의하면 공통 구현 함수임
trait은 상속이 가능함
&dyn Trait 하면 해당 trait의 구현을 만족하는 모든 타입을 뜻하게 됨.
메서드 호출에 dynamic binding(dispatch)이 일어남 (vtable)
trait을 변수로 두게 되면 struct의 크기를 예측할 수 없게 됨. (누가 구현체일줄 알고?)
generic 방식으로 타입을 표현하면 컴파일타임에 결정되므로 정적으로 예측이 가능해짐
indirection은 포인터 식으로 표현해서 그냥 실체는 heap에 있다 치고 그걸 deref 하는
trait 변수를 generic화 시키는 방법은 함수에 generic으로 타입을 정의하고, 구현부 전에 where 로 상세 trait을 전달하면 됨. 그냥 impl Trait 같은 식으로 줄여 쓸 수 있음
struct의 멤버를 generic하게 하는 방법도 동일함
Box: 스택의 로컬 변수를 힙의 메모리 영역으로 옮기기 위한 자료구조, indirection 식으로 trait을 관리