[swift] 구조체 (struct)

Snyong·2023년 9월 28일

swift

목록 보기
7/10
post-thumbnail

object?

  • 객체는 속성(property)과 행동(method)을 가지고 있음
  • struct와 class를 이용해서 구현할 수 있음

ex)

  • 객체: 사람
  • 속성: 피부색, 나이, 성별, 이름
  • 행동: 밥을 먹는다, 일을 한다

💡 struct vs class

공식문서에서는 공통점과 차이점을 아래와 같이 소개하고 있다

Structures and classes in Swift have many things in common. Both can:

  • Define properties to store values
  • Define methods to provide functionality
  • Define subscripts to provide access to their values using subscript syntax
  • Define initializers to set up their initial state
  • Be extended to expand their functionality beyond a default implementation
  • Conform to protocols to provide standard functionality of a certain kind

Classes have additional capabilities that structures don’t have:

  • Inheritance enables one class to inherit the characteristics of another.
  • Type casting enables you to check and interpret the type of a class instance at runtime.
  • Deinitializers enable an instance of a class to free up any resources it has assigned.
  • Reference counting allows more than one reference to a class instance.

강의에서는 친절하게 한국말로 번역해줬다

✅ 공통점

  • 프로퍼티(속성)를 정의해서 값을 저장할수 있음
  • 메소드(행동)를 정의해서 기능을 제공할수 있음
  • 생성자를 정의해서 초기상태를 세팅할수 있음
  • 확장을 이용해서, 기본 구현외 추가 기능을 더할수 있음
  • 프로토콜을 구현해서 특정 기능을 제공할수 있음

✅ 차이점

  • 클래스는 상속을 시킬수 있음
  • 클래스는 레퍼런스 카운팅을 통해 클래스 인스턴스에 대한 하나 이상의 참조를 허용
  • 클래스는 deinitializer 호출시, 이미 할당된 리소스에서 해제 할수 있음

1. struct 만들기

  • struct 키워드를 이용하여 생성할 수 있다
struct Movie {
    var name: String
}

var movie = Movie(name: "탑건")
print(movie.name)

movie.name = "탑건:매버릭"
print(movie.name)

2. property 만들기

  • 객체는 속성을 가지고 있고, 그것을 우리는 property 라고 부른다
  • name처럼 값을 저장하는 stored property 가 있다
  • 저장된 값이 아닌 계산된 값을 반환하는 computed property 도 있다
struct Movie {
    var name: String // stored property
    var director: String // stored property
    
    var description: String { // computed property
        return "\(name) is \(director)'s best movie"
    }
}

var movie = Movie(name: "탑건", director: "놀란")
print(movie.description)

property observers

  • property 값이 변경되는 것을 감지할 수 있다
struct Task {
    var name: String // stored property
    var progress: Int {
        didSet {
            print("Current progress: \(progress)%")
        }
    }
    
    var isDone: Bool { // computed property
        return progress == 100
    }
}

var task = Task(name: "Very Important Taks", progress: 0)

task.progress = 30
task.progress = 50
task.progress = 90

/*
 Current progress: 30%
 Current progress: 50%
 Current progress: 90%
 */

3. method 만들기

  • 객체는 행동(기능)을 가지고 있고, 그것을 method 라고 부름
  • 객체가 가지고 있는 함수라고 생각하면 됨
  • func 함수를 이용해서 구현함
struct Student {
    var name: String
    var major: String
    var knowledge: Double
    
    func didFinalTest() -> Int {
        let howMuchIDontknow = (1-knowledge) * 100
        let score = 100 - Int(howMuchIDontknow)
        return score
    }
}

var student = Student(name: "Jason", major: "CS", knowledge: 0.5)

let score = student.didFinalTest() // 50

mutating method

  • struct 인스턴스 생성시 let 선언 → property 변경 불가능
  • struct 인스턴스 생성시 var 선언 && store property가 let으로 선언 → property 변경 불가능
  • struct 인스턴스 생성시 var 선언 && store property가 let으로 선언 → property 변경 가능

💡 struct 에서 methodstored property 값을 변경하는 경우, mutating 키워드를 메소드 앞에 붙여주어야함

struct Student {
    let name: String
    var major: String
    var knowledge: Double
    
    func didFinalTest() -> Int {
        let howMuchIDontknow = (1-knowledge) * 100
        let score = 100 - Int(howMuchIDontknow)
        return score
    }
    
    mutating func didStudy() {
        if(knowledge >= 1) {
            knowledge = 1
        }
        else {
            knowledge += 0.1
        }
    }
}

var student = Student(name: "Jason", major: "CS", knowledge: 0.5)

let score1 = student.didFinalTest() // 50

student.didStudy()
student.didStudy()

let score2 = student.didFinalTest() // 70

//student.name = "ddd" // 에러 발생

💭 String struct 톺아보기

String이라는 글자 위에 마우스를 두고
⌃ – control + ⌘ - command + click 혹은
⌘ - command + click 후 Jump to Definition

let str: String = "Hello Swift"

print(str.count)  //  11

print(str.sorted())  //  [" ", "H", "S", "e", "f", "i", "l", "l", "o", "t", "w"]
print(str.split(separator: " "))  // ["Hello", "Swift"]
print(str.uppercased())  // HELLO SWIFT
print(str.hasPrefix("Hi")) // false

그럼 String도 struct로 이루어진 것을 확인할 수 있다!
count, sorted, split, uppercased, hasPrefix 등을 사용할 수 있다

initializer (생성자)

  • 해당 struct를 만들수 있게 해주는 특별한 타입의 메소드이다
  • init 키워드를 이용하여 생성한다
  • struct는 meberwise initializer가 기본으로 따라온다 (공식문서 사진 참조)

struct iPhone {
    var model: String
    
    init() {
        model = "iPhone13"
    }
}

let iPhone13 = iPhone()

현재 객체 지정하기

  • method에서 현재 객체를 지칭할때 self 키워드를 이용한다
  • 특히 initializer에서 파라미터와 내부 프로퍼티 이름간 구분을 지어줄때 용이하다
struct iPhone {
    var model: String
    
    init(model: String = "iPhone1 3") {
        self.model = model
    }
}

let iPhone13 = iPhone()

Lazy properties

  • 퍼포먼스 측면에서 인스턴스 생성시, 프러퍼티가 쓰이는 시점에 생성하는 방법이 있음
  • laxy 키워드를 사용하면 쓰이는 시점에 생성 가능
struct Transactions {
    init() {
        print("Loading self history.. ")
    }
}

struct SecondHandItem {
    var name: String
//    var history: Transactions = Transactions()
    lazy var history: Transactions = Transactions()
    
    init(name:String) {
        self.name = name
    }
}

var usedMacbook = SecondHandItem(name: "M1 MacBook")

struct Transactions {
    init() {
        print("Loading self history.. ")
    }
}

struct SecondHandItem {
    var name: String
    var history: Transactions = Transactions()
//    lazy var history: Transactions = Transactions()
    
    init(name:String) {
        self.name = name
    }
}

var usedMacbook = SecondHandItem(name: "M1 MacBook")

static Methods & Properties

  • 개별 인스턴스와 달리, 해당 타입의 속성, 해당 타입 자체의 메소드를 만들어야 할때가 있음
    → 타입 메소드, 타입 프로퍼티라고 부름
  • static 키워드를 이용하여 타입의 속성 및 메소드 정의
struct FCLecture {
    static var academyName: String = "Fast Campus"
    var name: String
}

var iOSLecture = FCLecture(name: "iOS 강의")
var backendLecture = FCLecture(name: "백엔드 강의")

print(iOSLecture.name) // "iOS 강의"
print(backendLecture.name) // "백엔드 강의"
print(FCLecture.academyName) // "Fast Campus"

Access Control

  • 외부 객체가 현재 객체를 임의로 수정하지 못하도록 접근제어를 할 수 있다.
  • (외부) public > internel > fileprivate > private (내부)
struct UserAccount {
    var id: String
    var bill: Int
    var name: String
    
    init(id: String, bill: Int, name: String) {
        self.id = id
        self.bill = bill
        self.name = name
    }
    
    func billDescription() -> String {
        return "\(id)'s billing amount :\(bill)"
    }
}


var user01 = UserAccount(id: "1234", bill: 400, name: "Mike")

user01.bill = 100 // 이러한 접근을 불가능하게 막아야한다
user01.id = "1123" // 이러한 접근을 불가능하게 막아야한다

let billDescription01 = user01.billDescription()

접근제어가 제대로 되지 않은 경우

struct UserAccount {
    private var id: String
    private var bill: Int
    var name: String
    
    init(id: String, bill: Int, name: String) {
        self.id = id
        self.bill = bill
        self.name = name
    }
    
    func billDescription() -> String {
        return "\(id)'s billing amount :\(bill)"
    }
}


var user01 = UserAccount(id: "1234", bill: 400, name: "Mike")

//user01.bill = 100
//user01.id = "1123"

let billDescription01 = user01.billDescription()

접근제어가 제대로 된 경우

0개의 댓글