Apple 제공 Swift 프로그래밍 가이드(3.0.1)의 Classes and Structures 부분을 공부하며 정리한 글입니다. 개인적인 생각도 조금 들어가있습니다.
들어가며
클래스(Class)와 구조체(structure)는 프로그램의 범용적이며 유연한 코드 블럭을 만들기 위해 사용된다. 클래스와 구조체에 기능을 추가하기 위해 프로퍼티와 메서드를 정의할 수 있다. 또한 Swift에서는 커스텀 클래스와 구조체를 만들 때 인터페이스와 구현부를 다른 파일로 나눌 필요가 없이, 하나의 파일에 구현을 해놓으면 외부 인터페이스를 알아서 만들어준다.
<note> 클래스의 인스턴스는 전통적으로 object 라고 부르지만 Swift의 클래스와 구조체는 다른 언어에 비해 기능(functionality)에 많이 가깝다. 이 챕터에서는 instance 라는 일반적인 용어를 사용한다.
Comparing Classes and Structures
클래스와 구조체의 공통점
프로퍼티 정의 (값 저장)
메서드 정의 (기능 제공)
서브스크립트 정의 (서브스크립트 문법을 이용해 값에 접근)
이니셜라이저 정의 (초기 상태 setup)
expand (확장) 가능
프로토콜 따를 수 있음 (conform)
클래스만 할 수 있는 것
상속
타입 캐스팅(Type casting) - 런타임에 클래스 인스턴스의 타입을 체크하고 변환할 수 있다
Deinitializers - 클래스의 인스턴스에 할당됐던 리소스들을 free up
Reference counting - 클래스 인스턴스를 한 번 이상 참조 가능 (* Value Type인 구조체는 Reference counting이 아니라 항상 copy 방식)
<Definition Syntax>
class SomeClass {
}
struct SomeStructure {
}
struct Resolution {
var width = 0
var height = 0
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
<Class and Structure Instances>
//이니셜라이저를 사용하여 인스턴스 생성
let someResolution = Resolution()
let someVideoMode = VideoMode()
<Accessing Properties>
print("The width of someResolution is
\(someResolution.width)")
// Prints "The width of someResolution is 0"
print("The width of someVideoMode is
\(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is 0"
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now
\(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is now 1280"
// objective-c와 다른 점 :
// 구조체 프로퍼티가 가진 내부프로퍼티의 값을 외부에서 직접 설정가능
<Memberwise Initializers for Structure Types>
모든 구조체는 기본적으로 memberwise initializer를 가지고 있다. 이것을 이용해 구조체의 멤버 프로퍼티들의 값을 설정하면서 구조체 인스턴스를 만들 수 있다. 클래스는 기본적으로 가지고 있지 않다.
let vga = Resolution(width: 640, height: 480)
Structures and Enumerations Are Value Types
Value Type이란 상수/변수에 할당될 때, 함수에 파라미터로 넘어갈 때 그 값이 복사(copy)되는 타입이다. Swift의 기본적은 타입들(integers, floating-point numbers, Booleans, strings, arrays and dictionaries)은 전부 value type이며 내부적으로는 구조체로 구현되어 있다. 모든 구조체와 ENUM은 value type이고 따라서 그 내부의 프로퍼티들은 전달될 때 전부 copy가 된다.
// 구조체 예제
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048
print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"
print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"
// ENUM 예제
enum CompassPoint {
case north, south, east, west
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection = .east
if rememberedDirection == .west {
print("The remembered direction is still .west")
}
// Prints "The remembered direction is still .west"
Classes Are Reference Types
Reference Type이란 상수/변수에 할당될 때, 함수에 파라미터로 넘어갈 때 그 값이 복사(copy)되지 않고, 같은 인스턴스의 참조(reference)가 사용되는 타입이다.
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
print("The frameRate property of tenEighty is now
\(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"
//tenEighty와 alsoTenEighty는 둘 다 let으로 선언된 상수
//상수 자체의 값은 변할 수 없고, 그 내부값만 변할 수 있다
<Identity Operators>
Reference type을 가지는 두 상수/변수가 서로 같은 인스턴스를 참조하고 있는지 체크하기 위해 Identical to (===) 연산자가 생겼다.
Identical to (===)
Not identical to (!==)
이 연산자는 기존의 equal to (==) 연산자와는 다른 것이다.
Identical to (===) : 두 상수/변수가 정확히 같은 인스턴스를 가리킨다
Equal to (==) : 두 인스턴스가 같은 값을 가진다
커스텀 클래스나 구조체를 정의할 때, 두 인스턴스가 어떤 경우에 Equal to (==) 가 될 것인지를 따로 정의할 수 있다.
if tenEighty === alsoTenEighty {
print("두 상수는 같은 인스턴스를 가리킨다.")
}
// Prints "두 상수는 같은 인스턴스를 가리킨다."
<Pointers>
C나 C++ 등에서는 메모리 주소를 가리키기 위해 포인터를 사용했다. Swift에서 레퍼런스 타입의 인스턴스를 가리킬 때 사용되는 상수/변수는 포인터와 비슷하지만, 메모리 주소를 직접적으로 가리키는 것도 아니고, 별표(*)를 붙이지 않아도 된다.
Choosing Between Classes and Structures
아래 조건에 해당하면 클래스 보다는 구조체를 사용하라.
연관된 데이터들을 캡슐화하는 것이 주목적일 때
캡슐화된 값들이 다른 곳으로 전달될 경우 참조가 아닌 복사가 되어야 할 때
구조체에 저장될 프로퍼티들이 value type일 때
이미 존재하는 타입으로부터 프로퍼티/기능 상속이 필요하지 않은 경우
구조체를 사용하기 좋은 케이스
Double형의 width, height 프로퍼티를 캡슐화하는 기하학적 모형의 사이즈
Int형의 start, length 프로퍼티를 캡슐화하는 Range 접근 방법
Double형의 x, y, z 프로퍼티를 캡슐화하는 3D 좌표
이 외의 모든 경우에는 클래스를 선택하라. 실질적으로 대부분의 커스텀 데이터형은 구조체가 아니라 클래스이다.
Assignment and Copy Behavior for Strings, Arrays, and Dictionaries
Swift의 기본 데이터 타입은 구조체로 내부구현이 되었으며 따라서 value type이다. String, Array, Dictionary 등이 여기에 해당한다. 즉 이것들은 새로운 상수/변수에 할당되거나 함수 파라미터로 넘어갈 때 복사가 된다.
그러나 Foundation에서의 기본 데이터 타입, 예를 들어 NSString, NSArray, NSDictionary 등은 클래스로 내부구현이 되어있다. 따라서 이것들은 참조가 전달되는 방식이다.
<note> Swift에서의 copy는... 복사가 필요한 시점에 actual copy가 발생하는 방식이다. 예를들어 array를 함수에 넘기면 그때는 일단 가리키고만 있다가, 그 array가 변경되는 시점에 복사가 된다.
'Swift 공식 가이드 > Swift 3' 카테고리의 다른 글
Methods (0) | 2017.03.01 |
---|---|
Properties (0) | 2017.02.27 |
Enumerations (0) | 2017.02.27 |
Closures (0) | 2017.02.21 |
Functions (0) | 2017.02.19 |