Open Do-hyun-Kim opened 1 year ago
struct Person {
var name: String
var age: Int
func greet() {
print("Hello, I'm \(name) and I'm \(age) years old.")
}
mutating
키워드를 사용한다.mutating func greet() {
self.name = "이름"
}
하나의 인스턴스를 공유해야 하는 경우가 아니라 각각의 인스턴스를 사용해야 하는 것이 합당하면 struct
를 사용한다.
아래의 예시는 참조타입인 class
였다면 하나의 인스턴스를 공유하지만, struct
이기에 값 복사가 이루어져 다른 인스턴스를 사용하게 된다.
// create an instance of Person
var person1 = Person(name: "Alice", age: 25)
// create another instance by copying person1
var person2 = person1
// modify person2's name
person2.name = "Bob"
// print person1's name
print(person1.name) // Alice
// print person2's name
print(person2.name) // Bob
Swift 에서 struct
는 class
가 가지는 거의 모든 기능을 제공하고 있다.
하지만, class
가 가지는 OOP 로서의 중요한 '상속' 기능을 지원하고 있지는 않다. 상속이 OOP 관점에서 중요한 이유는 부모 클래스로부터 물려받는 메서드와 프로퍼티들이 재사용 가능하며, 이들을 overriding
하여 다형성을 구현할 수 있기 때문이다.
Swift 언어가 공식적으로 지향하는 프로그래밍 패러다임이 있는데 이가 바로 '프로토콜 지향 프로그래밍(POP)' 이다.
POP 는 참조타입은 class
보다 값타입인 struct
를 지향하는 프로그래밍 패러다임이다. 참조 타입으로부터의 오류 최소화와 자요로움을 추구한다. POP의 특징은 아래와 같다.
POP를 적극 활용하면 상속을 지원하지 않는 struct
에서도 다형성을 충분히 구현할 수 있게 된다.
// define a protocol for vehicles
protocol Vehicle {
// define some properties
var currentSpeed: Double { get set }
// define some methods
func start()
func stop()
}
extension Vehicle {
func start() {
print("Starting...")
}
func stop() {
print("Stopping...")
}
}
struct Car: Vehicle {
var currentSpeed = 0.0
mutating func stop() {
print("Stopping...(overriding)")
currentSpeed = 0
}
func honk() {
print("Beep beep!")
}
}
var car = Car()
car1.start() // "Starting..."
car1.stop() // "Stopping...(overriding)"
car1.honk() // "Beep beep!"
Race Condition
, Dead Lock
등의 위험이 없기 때문에 별도 숙고 없이 사용 해도 되지만 Refrence Type인 Class 같은 경우 Thread Safe
에 숙고해야 하야 한다.Thread Safe
Race Condition
두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나, 쓸 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어 졌는지에 따라 그 실행 결과가 달라지는 상황을 말한다.
Sturct
를 사용하는 이유는 클래스 보다 객체 생성 비용이 훨씬 적게 들기 때문이다.
Class
보다 객체 생성 비용이 훨씬 적게 든다.Struct
에서 프로퍼티 값을 변경 하기 위해서는 mutating
키워드를 통해 내부 프로퍼티 값을 변경 시킬 수 있습니다.Struct
내부 에서 프로퍼티 값을 수정 하지 않고 새로운 인스턴스를 생성하여 값을 변경 하도록 구현 하면 불변 객체로 만들 수 있기에, 객체가 단순해 지며 안전해 지는 여러 장점이 있다.// 권장되지 않는 방식
struct Complex {
private var real: Double
private var imaginary: Double
init(real: Double, imaginary: Double) {
self.real = real
self.imaginary = imaginary
}
// 자기 자신의 프로퍼티를 변경하려 할 경우 mutating 키워드를 추가해야 합니다.
mutating func add(_ complex: Complex) {
real += complex.real
imaginary += complex.imaginary
}
}
struct Complex {
private let real: Double
private let imaginary: Double
init(real: Double, imaginary: Double) {
self.real = real
self.imaginary = imaginary
}
func plus(_ complex: Complex) -> Complex {
return Complex(real: real + complex.real, imaginary: imaginary + complex.imaginary)
}
}
Int
, Double
, String
등 기본 자료형은 구조체Array
, Dictionary
, Set
(Collection Type)은 Generic Structure nil
또한 구조체다른언어와 다르게 스위프트의 구조체는 클래스에서 사용할 수 있는 다양한 요소들을 사용할 수 있고 , Class보다 복잡성이 적기 때문에 디폴트로 구조체를 사용하기를 공식문서에서도 권장하고 있음
Struct 는 Class 와 공통점이 많다
Class는 구조체에 없는 추가적인 기능이 있다.
이처럼, Class가 지원하는 기능이 Struct에 비해 많기 때문에, 복잡성이 증가한다.
Struct 정의 구문
let originalLang = Study()
멤버별 초기화 구문
print("I studied (anotherLang.language) for (anotherLang.month) months")
// I studied Swift for 2 months