[Swift 기초] 사용자정의타입
2022. 3. 18. 18:09ㆍSwift 기초 정리
728x90
//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎
1. 구조체
struct 이름 {
/* 구현부 */
}
struct Sample{
//타입안에 들어가있는 변수: 프로퍼티
//인스턴스 프로퍼티
var mutableProperty: Int //가변 프로퍼티
let immutableProperty: String //불변 프로퍼티 - 인스턴스 생성 후 수정할 수 없음
//타입 프로퍼티
static var typeProperty: Int
//타입안에 들어가있는 함수: 메서드
//인스턴스 메서드
func instanceMethod(){
}
//타입 메서드
static func typeMethod(){
}
}
- 구조체(Structures): 서로 다른 자료형의 변수들을 묶어 하나의 새로운 자료형을 만들 수 있으며, 이 새로운 자료형을 구조체(struct)라고 한다.
- 속성과 메소드를 가질 수 있다.
- 값타입
1-1. 구조체 사용
struct Sample {
var mutableProperty: Int = 100
let immutableProperty: Int = 100
static var typeProperty: Int = 100
func instanceMethod(){
}
static func tyepMethod(){
}
}
//인스턴스 선언
var test: Sample = Sample()
//프로퍼티 접근 - 접근연산자(.)
test.mutableProperty
1-2. 가변 인스턴스와 불변 인스턴스
- 불변 프로퍼티는 인스턴스 생성 후 수정할 수 없다. (let)
- 'immutableProperty' is a 'let' constant
- 불변 인스턴스는 아무리 가변 프로퍼티라도 인스턴스 생성 후에 수정할 수 없다.
- 'immutable' is a 'let' constant
//가변 인스턴스 생성
var mutable: Sample = Sample()
mutable.mutableProperty = 200 //200
mutable.immutableProperty = 200 //'immutableProperty' is a 'let' constant
//불변 인스턴스 생성
let immutable: Sample = Sample()
immutable.mutableProperty = 200 //'immutable' is a 'let' constant
1-3. 인스턴스와 타입
struct Student {
var name: String = "noName"
var `class`: String = "stopStudy"
//타입 메서드
static func selfIntroduce(){
print("인스턴스를 생성하지 않는 타입입니다.")
}
//인스턴스 메서드
//self는 인스턴스 자신을 지칭
func selfIntroduce(){
print("\\(self.class)반 \\(name)입니다.")
}
}
//타입 메서드 사용 - 인스턴스 생성 X
Student.selfIntroduce() //인스턴스를 생성하지 않는 타입입니다.
//인스턴스 생성
var makeInstance: Student = Student()
makeInstance.name = "4학년"
makeInstance.class = "응애"
makeInstance.selfIntroduce() //응애반 4학년입니다.
1-4. 구조체의 초기화(init)
struct Celsius{
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double){
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double){
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
1-5. 구조체의 변경가능, 불가능 속성
- 구조체의 인스턴스 생성 후에는 메소드를 통해서 해당 인스턴스의 속성을 변경할 수 없다. 하지만 → 메소드가 구조체의 프로퍼티를 변경하게 하려면 mutating 사용
- 메소드의 디폴트 상태는 변경 불가능(immutable)이다. struct의 디폴트 변경모드가 변경 가능(mutable) 일 경우 내부 속성의 변경이 가능하므로 버그의 원인이 되며, 예측가능하지 않다.
- Mark method ‘mutating’ to make ‘self’ mutable
- 구조체의 메소드는 immutable로 프로그램의 안정성에 기여하고 버그를 줄이는 역할을 한다.
- 구조체 인스턴스가 상수 타입의 변수에 할당될 때는 mutating을 사용할 수 없다.
- class의 메소드는 mutable 하다.
struct Point0{
var x = 0.0, y = 0.0
//func moveByX(deltaX: Double, deltaY: Double){
// x += deltaX
// y += deltaY
//}
//Mark method ‘mutating’ to make ‘self’ mutable
//메소드가 프로퍼티의 값을 변경가능하다 를 명시: mutating
mutating func moveByX(deltaX: Double, deltaY: Double){
x += deltaX
y += deltaY
}
}
var somePoint = Point0()
somePoint.x = 100
somePoint.y = 100
somePoint.moveByX(deltaX: 2.0, deltaY: 3.0)
print(somePoint.x) //102.0
2. 클래스
class 이름 {
/* 구현부 */
}
class Sample {
//가변 프로퍼티
var mutableProperty: Int = 100
//불변 프로퍼티
let immutableProperty: Int = 100
//타입 프로퍼티
static var typeProperty: Int = 100
//인스턴스 메서드
func instanceMethod() {
}
//타입 메서드
//static - 상속 받았을 때 재정의 불가 타입 메서드
static func typeMethod(){
}
//calss - 상속 받았을 때 재정의 가능 타입 메서드
class func classMethod() {
}
}
- 클래스(Class): 클래스는 구조체와 같이 서로 다른 자료형의 속성과 메소드를 포함한다. 상속을 통해 자식 클래스에 자신의 속성과 메소드를 물려줄 수 있다.
- 다중상속 X
- 속성과 메소드를 가질 수 있다.
- 참조타입
2-1. 클래스 사용, 참조정보 수정
//인스턴스 생성 - 참조정보 수정 가능(var)
var mutableReference: Sample = Sample()
mutableReference.mutableProperty = 200
//인스턴스 생성 - 참조정보 수정 불가(let)
let immutableReference: Sample = Sample()
//클래스의 인스턴스는 참조타입이므로 let으로 선언되었더라도 인스턴스 프로퍼티의 값 변경이 가능하다(var mutableProperty)
immutableReference.mutableProperty = 300
//참조타입이라도 불변 인스턴스는 인스턴스 생성 후에 수정할 수 없다.
//immutableReference.immutableProperty = 300
//참조정보를 변경할 수는 없다.
//immutableReference = mutableReference
//타입 프로퍼티 및 메서드 - 인스턴스에서는 사용할 수 없다.
Sample.typeProperty = 300
Sample.typeMethod()
- 구조체와 다르게 클래스에서 let으로 인스턴스를 생성해도 가변 인스턴스 프로퍼티의 값은 변경할 수 있다.
- let immutableReference - var mutableProperty
3. 클래스와 구조체
3-1. 클래스와 구조체의 유사점
- 값을 저장할 속성을 정의한다.
- 기능을 위한 메소드를 정의한다.
- 멤버 속성의 설정과 검색을 위해서 메소드를 만들 수도 있으나 subscript을 사용하여 인덱스로 값을 편리하게 설정하고 검색할 수 있다.
- 초기상태를 설정하기 위한 init이라는 초기설정자를 제공한다.
- 기본 구현내용을 확장하기 위한 기능을 제공한다(extension)
3-2. 클래스와 구조체의 차이점(클래스는 구조체가 가지지 못한 다음 기능을 가진다.)
- 부모 클래스의 특성을 상속받는 기능이 가능하다.
- 클래스 인스턴스를 형을 검사하고 번형 하여 런타임시에 형변환을 할 수 있다.
- 할당된 임의의 리소스를 해지하는 deinitializer를 가진다.
- 클래스 인스턴스는 참조 카운터를 하나 이상 허용한다.
4. 열거형
enum 변수명 {
case 멤버1, 멤버2, ...
}
- 열거형(enumeration 또는 enum): 서로 연관된 상수 집합에 사용되는 정의된 타입
- 타입 안전이 보장됨: 프로그래밍 언어에서 타입 에러를 방지하는 것
- 타입 에러: 기대하는 타입과 제공된 타입 간에 차이가 있을 때 발생
- 변수가 가질 수 있는 가능한 값들을 나열해 놓은 타입
- 값의 종류가 일정한 범위로 정해 있을 때 쓰는 것이 편리
- 각 case 그 자체가 고유의 값
- C언어는 디폴트로 멤버에 정수를 할당하지만 Swift에서는 정수 할당 여부를 선택할 수 있다.
4-1. 열거형 사용
- 열거형 예시) 요일 - 유사한 데이터의 제한된 집합
enum Weekday {
case mon
case tue, wed
case thu, fri, sat, sun
}
- enum 키워드는 열거형을 나타냄
- {} 열거형을 정의하는 코드 블록이 포함
- case 키워드는 열거형 멤버를 정의할 때 사용
- Week.Monday Week 타입이면서 특정 Week 값을 갖는 변수를 생성
var day = Week.Monday //Week 타입의 변수를 선언 day = .Tuesday //값을 변경할 때는 더 이상 참조 표기(Week.)를 하지 않아도 된다 var mon:Week = .Monday //명시적인 타입 선언도 사용할 수 있다
- 값을 변경할 때는 더 이상 참조 표기(Week.)를 하지 않아도 된다.
- 명시적인 타입 선언도 사용할 수 있다
- 열거형 타입과 케이스를 모두 사용해도 된다.
- 타입이 명확하다면 .케이스 처럼 사용해도 무방하다.
- 타입 안전 보장
day = .holiday //'Week' 유형에는 'holiday' 구성원이 없습니다.
- switch문의 비교 값에 열거형 타입이 위치할 때 모든 열거형 케이스를 포함하면 default 작성할 필요는 없다.
4-2. 튜플을 멤버값으로 사용하는 열거형
enum Barcode{
case UPCA(Int, Int, Int, Int), QRCodes(String)
}
var productBarcode = Barcode.UPCA(1, 1, 1, 1)
productBarcode = .QRCodes("qr")
//switch문에서 사용할 때
switch productBarcode{
case .UPCA(let n1, let n2, let n3, let n4):
print("UPCA: \\(n1), \\(n2), \\(n3), \\(n4)")
case .QRCodes(let productCode):
print("QR: \\(productCode)")
}
4-3. 원시값
enum 변수명: 자료형 {
case 멤버 1 = 원시값1, 멤버2 = 원시값 2, ...
}
- 원시값(Raw values): 멤버가 가지는 이름에 데이터 값을 부여할 수 있다. 주로 숫자를 할당하여 편리하게 이용할 수 있다.
- rawValue 속성을 이용해서 원시값을 읽어올 수 있다.(읽기 전용)
- case 별로 각각 다른 값을 가져야 한다.
enum Planet: Int{
case Mercury = 1, Venus, Earth, Mars, Jupitor, Saturn, Uranus, Neptune
}
print(Planet.Mercury) //Mercury
print(Planet.Mercury.rawValue) //1
print(Planet.Venus.rawValue) //2
//정수 타입일 때 원시값을 지정하지 않으면 0부터 시작
enum Planets: Int{
case Mercury, Venus, Earth, Mars, Jupitor, Saturn, Uranus, Neptune
}
print(Planets.Mercury.rawValue) //0
print(Planets.Venus.rawValue) //1
//정수타입 뿐만 아니라 다른 타입도 원시값으로 지정 가능
enum School: String{
case elementry = "초등", middle = "중등", high = "고등"
case university
}
print(School.elementry) //elementry
print(School.elementry.rawValue) //초등
print(School.university.rawValue) //university - case의 이름을 원시값으로 사용
- 정수 타입일 때 원시값을 지정하지 않으면 0부터 시작
- Hashable 프로토콜을 따르는 모든 타입이 원시값의 타입으로 지정될 수 있다.
- 열거형의 원시값 타입이 String일 때, 원시값이 지정되지 않았다면 case의 이름을 원시값으로 사용
4-4. 원시값을 통한 초기화
- rawValue를 통해 초기화할 수 있다.
- rawValue가 할당되지 않은 case가 있을 수 있으므로 rawValue를 통해 초기화한 인스턴스는 옵셔널 타입이다.
//원시값을 이용하여 멤버를 찾고, 옵셔널 값 리턴
//옵셔널 바인딩
let somePlanet = Planet(rawValue: 100)
print(somePlanet) //nil
let anotherPlanet: Planet? = Planet(rawValue: 3)
print(anotherPlanet!) //Earth
4-5. 열거형 메서드
- swift의 열거형에는 메서드도 추가할 수 있다.
enum Month {
case dec, jan, feb
case mar, apr, may
case jun, jul, aug
case sep, oct, nov
func printMessage() {
switch self {
case .mar, .apr, .may:
print("따스한 봄~")
case .jun, .jul, .aug:
print("여름 더워요~")
case .sep, .oct, .nov:
print("가을은 독서의 계절!")
case .dec, .jan, .feb:
print("추운 겨울입니다")
}
}
}
Month.mar.printMessage()
// 따스한 봄~
참고하였습니다. 감사합니다.
https://yagom.net/courses/swift-basic/lessons/사용자정의-타입/
https://www.inflearn.com/course/창원대학교-박동규-교수의-swift-기초-강좌/lecture/1896?tab=curriculum
23.07.06 수정) Swift 쉽게, 더 쉽게
728x90
'Swift 기초 정리' 카테고리의 다른 글
[Swift 기초] 프로퍼티 (0) | 2022.03.31 |
---|---|
[Swift 기초] 참조타입과 값타입 (0) | 2022.03.19 |
[Swift 기초] 클로저 Closure (0) | 2022.03.14 |
[Swift 기초] 제너릭 (0) | 2022.03.11 |
[Swift 기초] 함수 (0) | 2022.03.11 |