구조체와 클래스
구조체와 클래스는 프로그래머가 데이털르 용도에 맞게 묶어 표현하고자 할 때 용이하다. 구조체와 클래스는 프로퍼티와 메소드를 사용하여 구조화된 데이터와 기능을 가질 수 있다. 하나의 새로운 사용자지정의 데이터 타입을 만들어주는 것이다. 스위프트에서는 구조체와 클래스의 모습과 문법이 거의 흡사하지만, 구조체의 인스턴스는 값 타입이고, 클래스의 인스턴스는 참조 타입이라는 큰 차이점이 존재한다. => ‘무엇이 전달되느냐’가 다르다. 예를 들어 어떤 함수의 전달인자로 값 타입의 값을 넘긴다면 전달될 값이 복사되어 전달되지만, 참조 타입이 전달인자로 전달될 때에는 값을 복사하지 않고 참조(주소)가 전달된다. 참조라는 것은 C, C++, Objective-C 등의 언어에서 사용되는 포인터와 유사한 개념이다. 단, 참조라는 것을 표현해주기 위한 표현인 에스터리스크(*)를 사용하지는 않는다.
(스위프트의 데이터 타입과 열거형은 값 타입이다.)
소스파일 하나에 여러 개의 구조체와 클래스를 정의하고 구현해도 문제가 없다. 또한 중첩 함수와 마찬가지로 구조체 안에 구조체, 클래스 안에 클래스 등과 같이 중첩 타입의 정의 및 선언이 가능하다.
- Note_명명법: 구조체와 클래스를 정의한다는 것은 새로운 타입을 생성해주는 것과 같으므로 기본 타입 이름(Int, String, Bool 등등)처럼 대문자 카멜케이스를 사용하여 이름을 지어준다. 프로퍼티와 메소드는 소문자 카멜케이스를 사용한다.
*구조체 정의
struct BasicInformation {
var name: String
var age: Int
}
BasicInformation 구조체는 String 타입인 name과 Int 타입인 age라는 저장 프로퍼티를 가진다.
*구조체 인스턴스의 생성 및 초기화
let meInfo: BasicInformation = BasicInformation(name: “JB”, age: 29)
meInfo.name = “JayB”
meInfo.age = 30
—————————————————————————————————————————————————
*클래스 정의
class Person {
var height: Float = 0.0
var weight: Float = 0.0
}
Person 클래스는 Float 타입인 height 와 float 저장 프로퍼티가 있다.
*클래스 인스턴스의 생성과 초기화
- Note_인스턴스와 객체: 일반적인 객체지향 프로그래밍 패러다임을 지향하는 언어에서는 클래스의 인스턴스를 객체라고 부르지만, 스위프트 공식 문서에서는 좀 더 한정적인 인스턴스라는 용어를 사용한다.
var meVar: Person = Person()
me.height = 123.4
me.weight = 123.4
var meLet: Person = Person()
me.height = 123.4
me.weight = 123.4
인스턴스가 생성되고 초기화된 후(이니셜라이즈된 후) 프로퍼티 값에 접근하고 싶다면 마침표(.)를 사용해라. 구조체와는 다르게 클래스의 인스턴스는 참조 타입이므로 클래스의 인스턴스를 상수 let으로 선언해도 내부 프로퍼티 값을 변경할 수 있다.
*클래스 인스턴스의 소멸
클래스의 인스턴스는 더는 참조할 필요가 없을 때 메모리에서 해제된다. 해제(소멸)되기 직전에 deinit이라는 메소드가 호출되는데, 클래스 내부에 deinit 메소드를 구현해주면 클래스의 인스턴스가 소멸되기 직전에 호출되므로 하고 싶은 일들을 행하게 할 수 있다. deinit 메소드를 디이니셜라이저[Deinitializer]라고 한다. deinit 메소드는 클래스당 하나만 구현할 수 있으며, 매개변수와 반환 값을 가질 수 있다.
class Person {
var height: Float = 0.0
var weight: Float = 0.0
deinit {
print(“Person 클래스의 인스턴스가 소멸됩니다.”)
}
}
var me: Person = Person()
me = nil // Person 클래스의 인스턴스가 소멸된다.
*구조체와 클래스의 차이
공통점(
-값을 저장하기 위해 프로퍼티를 정의할 수 있다.
-기능 수행을 위해 메소드를 정의할 수 있다.
-서브스크립트 문법을 통해 값(프로퍼티)에 접근하도록 서브스크립트를 정의할 수 있다.
-초기화될 때의 상태를 지정하기 위해 이니셜라이저를 정의할 수 있다.
-새로운 기능 추가를 위해 익스텐션을 사용할 수 있다.
-특정 기능을 수행하기 위해 특정 프로토콜을 준수할 수 있다. [?]
차이점
-구조체는 상속할 수 없다.
-타입 캐스팅은 클래스의 인스턴스에만 허용된다.
-디이니셜라이저는 클래스의 인스턴스에만 활용할 수 있다.
-참조 횟수 계산(Reference Counting)은 클래스의 인스턴스에만 적용된다. (사실 구조체는 값 타입이고, 클래스는 참조 타입이기에 당연한 거다.)
—————————————————————————————————————————————————
*스위프트의 기본 데이터 타입(Bool, Int, Array, Dictionary, Set 등등)은 모두 구조체다.
public struct String {
public init()
}
이 말인 즉, 기본 데이터 타입은 모두 값 타입이라는 뜻이다. 전달인자를 통해 데이터를 전달하면 모두 값이 복사되어 전달될 뿐!
—————————————————————————————————————————————————
*구조체와 클래스 선택해서 사용하기
구조체와 클래스는 모두 새로운 데이터 타입을 정의하고 기능을 추가한다는 점에서 같지만, 구조체 인스턴스는 항상 값 타입이고, 클래스 인스턴스는 참조 타입이다. 결국 생긴 것은 비하지만 용도가 다르다는 뜻! 프로젝트의 성격에 따라, 데이터의 활용 용도에 따라, 특정 타입을 구현할 때 둘 중 하나를 선택해야 한다.
Following Apple Guideline,
연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때,
캡슐화된 값이 참조되는 것보다 복사되는 것이 합당할 때,
구조체에 저장된 프로퍼티가 값 타입이며 참조되는 것보다 복사되는 것이 합당할 때,
다른 타입으로부터 상속받거나 자신이 상속될 필요가 없을 때,
"이런 때에! 구조체를 사용하기를 권한다."
좌표계(x, y 좌표 등), 물건의 크기(width, height, depth 등) 같은 경우에 구조체를 사용하자.
'STUDY > Swift' 카테고리의 다른 글
Swift 비교 연산자 (0) | 2018.06.29 |
---|---|
Swift nil 병합 연산자, 옵셔널 관련 연산자 (0) | 2018.06.29 |
Swift 클로저 [Closure] (0) | 2018.06.22 |
Swift 3.0 Thread 1:signal SIGABRT (1) | 2016.12.13 |
iOS 앱 실행과정 (0) | 2016.12.08 |