Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Struct 가 무엇이고 어떻게 사용하는지 설명하시오. #7

Open
Do-hyun-Kim opened this issue Aug 15, 2023 · 4 comments
Open
Labels
Swift Swift CS 개념 공부

Comments

@Do-hyun-Kim
Copy link
Contributor

No description provided.

@Do-hyun-Kim Do-hyun-Kim added the Swift Swift CS 개념 공부 label Aug 15, 2023
@vichye-1
Copy link

vichye-1 commented Aug 17, 2023

Struct 는 Class 와 공통점이 많다

  • 저장 프로퍼티 사용가능
  • 서브 스크립트 정의 가능
  • 초기화 정의 가능
  • extension 정의 가능

Class는 구조체에 없는 추가적인 기능이 있다.

  • 다른 클래스의 특성을 상속 가능
  • 타입 캐스팅 사용 가능
  • deinitalizers(초기화 해제 구문) 사용 가능
  • 참조 카운팅이 적용됨(참조 타입이기 때문)

이처럼, Class가 지원하는 기능이 Struct에 비해 많기 때문에, 복잡성이 증가한다.

  • 따라서 추론하기 쉬운 구조체를 사용하기를 선호하고, 특정 기능이 필요할 때 클래스를 사용한다.

Struct 정의 구문

struct SomeStructure {
// structure definition goes here
}
  • 구조체의 이름은 대문자로 시작해야하고, CamelCase를 사용해야한다.
  • Struct 안의 프로퍼티나 메서드들은 lowerCamelCase를 사용한다.
struct Study {
    var language = "Python"
    var month = 12
}

let originalLang = Study()

프로퍼티 접근

  • dot syntax(점 구문)로 인스턴스의 프로퍼티에 접근할 수 있다.
print("I studied \(originalLang.language) for \(originalLang.month) months")

// I studied Python for 12 months

멤버별 초기화 구문

  • 모든 구조체는 새로운 구조체 인스턴스의 멤버 프로퍼티를 초기화 할 때 자동적으로 '멤버별 초기화 구문(Memberwise initializer)'을 가지고 있다.
  • 하지만 클래스는 멤버별 초기화가 되지 않는다.
let anotherLang = Study(language: "Swift", month: 2)

print("I studied \(anotherLang.language) for \(anotherLang.month) months")

// I studied Swift for 2 months

📝 참고

@ronick-grammer
Copy link
Contributor

Struct란

  • 여러 다른 타입의 데이터들을 담을 수 있는 데이터 타입이다.
  • 값 타입이며, 힙(heap)이 아닌 스택(stack) 에 데이터가 할당된다.

Struct 정의

struct Person {
    var name: String
    var age: Int
    
     func greet() {
        print("Hello, I'm \(name) and I'm \(age) years old.")
    }

struct 메서드 내에서 프로퍼티를 변경하고자 할때에는 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를 사용해야만 하는 주요 이유

Swift 에서 structclass 가 가지는 거의 모든 기능을 제공하고 있다.

  • 생성자
  • 프로퍼티와 메서드
  • extension
  • Protocol 채택

하지만, class 가 가지는 OOP 로서의 중요한 '상속' 기능을 지원하고 있지는 않다. 상속이 OOP 관점에서 중요한 이유는 부모 클래스로부터 물려받는 메서드와 프로퍼티들이 재사용 가능하며, 이들을 overriding 하여 다형성을 구현할 수 있기 때문이다.

struct로 구현하는 다형성과 POP(Protocol Oriented Programming)

Swift 언어가 공식적으로 지향하는 프로그래밍 패러다임이 있는데 이가 바로 '프로토콜 지향 프로그래밍(POP)' 이다.
POP 는 참조타입은 class 보다 값타입인 struct 를 지향하는 프로그래밍 패러다임이다. 참조 타입으로부터의 오류 최소화와 자요로움을 추구한다. POP의 특징은 아래와 같다.

  • 코드의 중복을 최소화 한다.
  • 상속과 달리 필요한 것만 골라서 사용할수 있으며 참조추적 비용이 없어 가볍다
  • 값 타입도 상속처럼 공통된 기능을 쉽게 구현할 수 있다
  • Class 는 하나의 상속만 가능하고 수직적인 구조이지만 Protocol을 사용하면 수평적인 확장이 가능해진다
  • generic을 활용하여 자료형에 구애받지 않는 범용 코드를 작성할 수 있다.

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!"

📝 참고 사이트

@Do-hyun-Kim
Copy link
Contributor Author

Struct 가 무엇이고 어떻게 사용하는지 설명하시오

  • deep Copy 형식을 지원하며 Race Condition, Dead Lock 등의 위험이 없기 때문에 별도 숙고 없이 사용 해도 되지만 Refrence Type인 Class 같은 경우 Thread Safe 에 숙고해야 하야 한다.

Thread Safe

  • 여러 Thread가 한 자원에 동시에 접근하는 것을 막음 으로 써 "정확성"을 보장 하는 것을 의미한다. 기본적으로 Swift의 대부분 Type 같은 경우 Thread가 동시에 접근 가능한 Thread UnSafe의 특성을 가지고 있다.

Race Condition

  • 두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나, 쓸 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어 졌는지에 따라 그 실행 결과가 달라지는 상황을 말한다.

  • Sturct 를 사용하는 이유는 클래스 보다 객체 생성 비용이 훨씬 적게 들기 때문이다.

Struct 를 사용해야하는 이유

  • 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)
    }
}

📝 참고 사이트

@Hminchae
Copy link
Member

Struct

  • Memberwise Initalizer가 자동으로 만들어짐
  • Int, Double, String 등 기본 자료형은 구조체
  • Array, Dictionary, Set(Collection Type)은 Generic Structure
  • nil 또한 구조체
  • 구조체/열거형의 인스턴스는 값(value)타입, 클래스의 인스턴스는 참조(reference) 타입
  • 구조체는 상속불가함

Struct 사용 이유

  • 값 타입이기 때문에, 메모리의 스택 영역을 사용
  • 스택 영역은 각 스레드가 독립적으로 사용, 때문에 Thread-Safe 하다는 특징이 있음
  • 스택 영역은 스택 포인터만 이동시키면 되기 때문에 한번의 명령으로 할당과 해제 가능
  • 컴파일 타임에 할당 할 크기가 결정되기 때문에 메모리를 따로 관리해주지 않아도 됨(운영체제가 새로운 데이터를 할당할 영역을 따로 계산하지 않아도 됨)

이럴 때 Struct 를 쓰세요!

다른언어와 다르게 스위프트의 구조체는 클래스에서 사용할 수 있는 다양한 요소들을 사용할 수 있고 , Class보다 복잡성이 적기 때문에 디폴트로 구조체를 사용하기를 공식문서에서도 권장하고 있음

  • 고유한 값을 제어하지 않을 때, 구조체를 사용 : 외부에서 이미 고유성을 처리하고 있는 경우에, 앱 내에서 데이터의 고유성을 관리할 필요 없음
  • 상속과 공유 속성을 모델링 하고 싶을 때, 구조체와 프로토콜을 사용 : 구조체는 클래스처럼 다른 클래스를 상속할 수 없지만, 프로토콜을 통해 계층구조를 표현할 수 있다. 클래스는 클래스끼리만 상속을 만들 수 있는 반면, 프로토콜은 클래스, 열거형, 구조체가 모두 채택하도록 할 수 있음

📝 참조

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Swift Swift CS 개념 공부
Projects
None yet
Development

No branches or pull requests

4 participants