일부 언어는 소스파일 하나에 구조체 or 클래스 1개만 선언 가능하지만,
Swift는 여러 개의 구조체, 클래스 정의하고 구현할 수 있다!
+ 구조체 안의 구조체 / 클래스 안의 클래스 등 중첩 타입 정의 가능!!
- 구조체를 let으로 선언하면, 내부 프로퍼티 값 변경할 수 없다! (var로 선언 시 가능 )
- 클래스의 "인스턴스"는 "참조타입"이므로 let(상수)으로 선언해도 내부 프로퍼티 값 변경 가능!!!!
- 클래스의 Instance는 참조타입이므로, 참조할 필요가 없을 때 메모리에서 해제된다!
- 메모리 해제 직전에 deinit(소멸자)이 호출된다 ( deinit은 클래스 당 하나 구현 가능)
- 인스턴스 소멸 전에 데이터 저장, 소멸을 다른 객체에 알리는 등의 코드를 deinit{} 내부에 작성
- 프로퍼티 & 메서드 정의, 접근 가능
- 초기화를 위해 Initializer 정의 가능
- extension으로 확장 가능
- protocol 준수 가능
- 구조체는 상속 불가
- 클래스의 Instance만 DeInitializer 활용 가능
- 클래스 Instance만 Reference Counting 함 ( 클래스 인스턴스만 참조타입이므로 )
- 구조체는 상속 불가
- 타입캐스팅은 클래스의 인스턴스만 가능
- deinit은 클래스의 인스턴스만
- Reference counting은 클래스 인스턴스만
함수의 전달인자로 전달 되는 경우 & 새로운 변수에 할당될 때 모두!
- 값 타입 : 값이 복사되어 전달
- 참조 타입 : 값을 복사X, 주소(참조)를 전달!!
부연설명 :
* 함수의 전달인자로 값 타입 데이터 전달? => 메모리에 전달인자를 위한 인스턴스가 새로 생성
* 함수 전달인자로 참조 타입 전달? => 주소만 전달!
1. 캡슐화만이 목적일 때
2. 상속을 할 필요가 없을 때
3. 프로퍼티를 참조하는 것보다 복사하는 것이 합당할 때!
- 프로퍼티는 저장 프로퍼티(Stored Properties), 연산 프로퍼티(Computed Properties), 타입 프로퍼티(Type Properties)
- 프로퍼티 감시자(Property Observers)는 프로퍼티 값 변화를 관찰하여 특정 작업을 실행함 ( 저장 프로퍼티에만 적용 가능 )
- 가장 단순한 개념의 프로퍼티
- 구조체든 클래스든, Instance를 만들 때, 저장 프로퍼티에 값이 꼭 있어야한다!( 옵셔널 저장 프로퍼티 제외 )
- 구조체는 저장 프로퍼티 기본값을 지정하지 않아도, 알아서 해당 프로퍼티들 채우는 생성자 제공.
- 클래스는 옵셔널이 아닌 모든 프로퍼티들을 초기화할 수 있는 생성자를 사용자 정의 해주어야한다.
- 상수는 인스턴스 생성되기 전에 초기화 해야하므로 지연저장 불가
- 굳이 모든 저장 프로퍼티를 모든 인스턴스가 사용하지 않아도 될텐데, 지연저장 프로퍼티를 사용하면, 불필요한 성능 저하, 공간낭비 줄일 수 있다.
- 메서드로 구현해도 되는 것이지만,
1. 메서드로 구현할 경우 메서드 두 개 구현해야함.
2. 두 메서드가 분산되어 코드 가독성 나빠질 위험
3. 연산프로퍼티가 더 간편,직관적이다!
- But, 읽기 전용(Getter) 상태로 구현하기 쉽지만, 쓰기 전용 상태로는 구현할 수 없다!!!
예시)
같은 기능을 메서드가 아닌, 연산 프로퍼티로 구현한 예시
-> 하나의 프로퍼티에 대한 Getter, Setter가 모여있어 명확하고 직관적임을 알 수 있다.
- 프로퍼티 값이 새로 할당될 때마다 호출
- willSet => 프로퍼티 값이 변경되기 직전에 호출 ( 변경될 값을 매개변수로 줌 newValue)
- didSet => 프로퍼티 값이 변경된 직후에 호출 ( 변경되기 전 값을 매개변수로 줌 oldValue)
- 전역변수, 지역변수에도 Property Observer 달아줄 수 있다!
-> 일반 저장 프로퍼티 / 상속받은 연산프로퍼티 재정의 에서만 Property Observer 사용 가능!!
==> why? 연산 프로퍼티는 감시자를 사용할 필요도 없고 할 수도 없는 이유는, 연산프로퍼티 내부에서 값의 변화에 대한 구현이 다 가능하기 때문.
- 저장 프로퍼티, 지연저장 프로퍼티, 연산 프로퍼티와 같이 인스턴스가 생성될 때마다 생성되는 "인스턴스 프로퍼티"가 아닌,
Type 자체에 속하는 프로퍼티를 "타입 프로퍼티"라고 함
-인스턴스 생성과 상관 없이 타입 프로퍼티 값은 하나
- 해당 타입 모든 인스턴스가 공통으로 사용하는 값
- 모든 인스턴스에서 공용으로 접근, 값 변경할 수 있는 변수
* Swift에서는 클래스, 구조체, 열거형이 실행하는 기능을 캡슐화하여 인스턴스 메서드를 정의할 수 있다.
* 타입 자체와 관련된 기능을 하는 타입 메서드 ( 기존 언어에서의 클래스 메서드와 유사한 개념) 정의할 수 있다.
-## 구조체, 열거형이 메서드를 가진다는 것이 기존 언어와 Swift의 큰 차이!!!
- 인스턴스 메서드 :
특정 타입의 인스턴스에 속한 함수를 뜻함. => 기존 언어들에서의 클래스 내의 함수라고 생각하면 됨.
인스턴스 내부의 프로퍼티 값을 변경하거나 특정 연산 결과를 반환하는 등 인스턴스와 관련된 기능을 실행함.
위와 같은 컴파일 오류가 뜬다.
또한, let 으로 구조체 인스턴스를 생성할 경우, 내부 프로퍼티 값을 변경할 수 없다.
* 모든 인스턴스는 암시적으로 생성된 self 프로퍼티를 가짐 (자바의 this와 비슷)
* self는 다른 언어에서와 같이 인스턴스(본인)을 명확히 지칭하고자 할 때 사용함
## 같은 이름을 사용했을 때 Swift는 지역변수 -> 메서드 매개변수 -> 인스턴스 프로퍼티 순으로 추측!
아래 그림18번 줄처럼 self로 프로퍼티 level 을 명확히 지칭할 수 있다.
=> 인스턴스 자체를 바꿔 끼울 수 있다!! ( 클래스 Instance는 참조타입이므로 self프로퍼티에 다른 참조 할당 불가. but 구조체, 열거형 등 값 타입 인스턴스는 self 프로퍼티를 사용하여 자신 자체를 치환 가능)
=> 메서드 앞에 static 키워드를 사용하여 "타입 메서드"임을 나타냄
=> 클래스의 경우, static, class 두가지로 타입 메서드 명시.
==> static : 상속 후 override 불가 / class : 상속 후 override 가능
인스턴스는 사용 후 소멸 시점이 오면 소멸한다. 클래스 인스턴스의 소멸은 ARC와 관련됐고, 이니셜라이저는 상속된다.
- Swift의 init로 초기화 과정 구현 가능, 반환값은 없다.
- class, struct, enum 모두 func 키워드 없이 init(){ ...} 형태로 이니셜라이저 작성
- init ()도 매개변수를 가질 수 있고 여러개의 init() 정의 가능!
- 사용자정의 이니셜라이저를 하나라도 만들면, 기본 init()과 멤버와이즈 init (구조체 특권)을 사용할 수 없다.
- 초기화 후에 값이 확정되지 않은 저장 프로퍼티는 존재할 수 없다!
- 이니셜라이저를 통해 초깃값 할당 or 프로퍼티 기본값을 통해 저장 프로퍼티가 초기화될 때는 Property Observer 호출되지 않음!
- 초기화 과정에 값을 초기화해주지 않아도 됨.
- 옵셔널 property는, 초기화 과정에 값을 할당해주지 않는다면 자동으로 nil이 할당 됨
- 상수 저장 프로퍼티는 인스턴스 초기화 과정에서만 값 할당 가능, 이후 값 변경 불가
- 자식클래스에서 부모클래스 상수 프로퍼티 값 초기화 불가능
- 사용자 정의 이니셜라이저를 정의하면, 기본 init()과 멤버와이즈 init() 사용 불가능하므로, 초기화 위임 ( 정의한 init()을 다른 init()안에서 사용 -> 중복되는 코드 줄임)하려면 최소 2개의 init()을 정의해줘야한다.
- init 대신 init?(){ ...} 키워드 사용. => 실패한 경우 nil 반환
- class ~~ {
let a: SomeType = {
~~~연산
}()
}
위와 같이 프로퍼티 초기화에 클로저나 함수를 사용하면, 실행 시점은 인스턴스의 다른 프로퍼티 값이 설정되기 전이다!
즉, 클로저 내부에서 다른 프로퍼티 사용하여 연산 불가능!!
## 클로저 뒤 ()는 해당 클로저를 실행하기 위한 표현. ()가 없다면 클로저 그 자체가 할당되게 된다.
- Class 인스턴스에만 구현 가능! (참조 타입이니까)
- deinit 키워드 사용
- 메모리에서 해제되기 직전 원하는 작업 수행 가능!
- init()과 다르게 매개변수 갖지 않음!
Swift는 인스턴스 더 필요하지 않으면 자동으로 메모리에서 소멸시킴 (ARC)
## 인스턴스 내부에서 파일을 열었었다면 다시 저장하고 닫는 등의 작업, 데이터를 저장하는 작업에 사용
* open - public - Internal - fileprivate - private 순이다.
# open - 개방 접근수준 & 모듈 외부까지 (클래스에서만 사용)
# public - 공개 접근수준 & 모듈 외부까지
# Internal - 내부 접근수준 & 모듈 내부
# fileprivate - 파일외부비공개 접근수준 & 파일 내부
# private - 비공개 접근수준 & 기능 정의 내부
Swift언어7 - 함수형 프로그래밍_옵셔널 체이닝(?)과 빠른 종료(guard문) (0) | 2022.10.04 |
---|---|
Swift언어6 - 함수형 프로그래밍_클로저 (0) | 2022.10.01 |
Swift언어 복습노트 4 - 함수와 Optional (1) | 2022.09.10 |
Swift언어 복습노트 3 - 흐름제어 in Swift (0) | 2022.09.10 |
Swift언어 복습노트2 - 컬렉션 타입과 연산자 (0) | 2022.05.23 |