Structures and Classes
다른 언어와는 다르게 Swift 에서는 class 와 strucutre 에 대한 interface와
파일 을 분리할 필요가 없습니다.
Swift 에서는 하나의 파일에 structure 또는 class 를 정의하면, 자동으로 다른 코드에서 사용할 수 잇도록 외부 인터페이스가 구현됩니다.
Comparing Structures and Classes
Swift 에서 class 와 structure 는 많은 공통점을 가집니다.
•
property
•
method
•
subscript
•
initializer
•
extension 확장 가능
•
protocol 적용 가능
위에 대한 더 많은 정보는 다음의 링크들을 참조하세요
다만 Class 는 structure에게는 없는 기능들이 존재합니다.
•
Inheritance : 상속
•
Type cast : 타입 캐스팅
•
Deinitializer : 객체가 가지고 있는 자원 해제
•
Reference counting : 클래스의 객체가 여러번 참조 될 수 있게 허가
이에 대한 더 많은 정보는 다음의 문서들을 참조하세요
class 는 추가적인 기능을 제공하므로 이를 위해 비용이 소모됩니다. 일반적인 선에서는 structure 을 사용하세요. custom data type을 만들때는 structure 또는 enumeration 을 사용하세요.
이에 대한 더 자세한 비교는 아래의 문서를 참조하세요
Definition Sytax
Structure 와 class 는 구문이 매우 비슷합ㄴ디ㅏ.
struct SomeStructure {
// structure definition goes here
}
class SomeClass {
// class definition goes here
}
Swift
복사
class 와 structure 은 Swift 의 data type 입니다. UppperCamelCase 로 이름을 지으세요. 프로퍼티와 메서드들은 lowerCamelCase 를 사용하여 이름을 붙여주면 됩니다.
아래는 structure 와 class 의 정의의 예시입니다.
struct Resolution {
//stored prorperty
var width = 0
var height = 0
}
class VideoMode {
//stored prorperty
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String?
}
Swift
복사
Resolution 은 width and height 라는 두개의 stored property 를 가집니다. stored property 란 class 또는 structure 의 일부로 저장되는 상수 또는 변수를 이르는 말입니다.
Structure and Class Instance
앞서 정의한 struct 와 class 는 단지 type 에 대한 청사진일 뿐입니다. 정의만으로는 사용이 불가능합니다. 사용을 위해서 struct 또는 class 의 instance 를 생성해야합니다.
let someResolution = Resolution()
let someVideoMode = VideoMode()
Swift
복사
이러한 식으로 인스턴스를 생성할 수 있습니다.
가장 간단한 형태의 initializer 구문입니다. 위의 구문은 모든 프로퍼티를 초기값으로 설정하며 생성됩니다.
Accessing Properties
프로퍼티에 접근하기 위해서는 dot syntax 를 이용합니다. . 와 프로퍼티의 이름을 통해 프로퍼티에 접근이 가능합니다.
print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 0"
Swift
복사
프로퍼티의 프로퍼티에도 접근이 가능합니다.
print("The width of someVideoMode is \(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is 0"
Swift
복사
프로퍼티에 새 값을 할당하기위해서도 . 구문을 사용할 수 있습니다.
someVideoMode.resolution.width = 1280
print("The width of someVideoMode is now \(someVideoMode.resolution.width)")
// Prints "The width of someVideoMode is now 1280"
Swift
복사
Memberwie Initializers for Structure Types
모든 struct 들은 자동적으로 memberwise initializer 가 생성됩니다. 이를 이용해서 새 structrue instance 의 member 프로퍼티를 초기화 할 수 잇습니다. 다른 초기값으로 객체를 생성하려면 memberwise initializer 에 프로퍼티 이름과 함께 초기값을 전달해주면 됩니다.
let vga = Resolution(width: 640, height: 480)
Swift
복사
structure 와는 달리 class 에게는 meberwise initializer 가 기본으로 제공되지 않습니다.
Structures and Enumerations Are Value Types
value type 이란 자신의 값이 변수 또는 상수에 할당 또는 함수에 전달될 때 원본이 복제되는 type 을 의미합니다. 앞서 배운 대부분의 타입들이 value type 에 해당합니다.
integers, floating-point numbers, Booleans, strings, arrays and dictionaries
그리고 이들은 사실 strucutre 로 구현되어 있습니다.
모든 strutcure 과 enumeration 들은 value type 입니다. 이들의 객체 또한 value type 에 해당합니다.
어레이, 딕셔너리, 문자열 과 같은 Collection 들은 복사에 필요한 비용을 최소화 하기위해 최적화 기법을 사용합니다. 복사는 즉시 실행되지 않고 메모리공간을 공유하다, 저장된 원소의 수정이 일어나는 순간 복사가 시작됩니다.
아래는 앞선 Resolution 구조체에 대한 예시입니다.
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
Swift
복사
위 예시에서 cinema 와 hd 는 strutcure 의 instance 이므로 할당시 값은 동일하지만 전혀다른 객체로 복제됩니다.
cinema.width = 2048
Swift
복사
cinema 의 width 프로퍼티의 값을 변경하여도 hd 의 width 프로퍼티는 그대로입니다. 이는 서로 다른 메모리 공간을 점유하고있기 때문입니다.
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"
Swift
복사
열거형도 마찬가지입니다.
enum CompassPoint {
case north, south, east, west
mutating func turnNorth() {
self = .north
}
}
var currentDirection = CompassPoint.west
let rememberedDirection = currentDirection
currentDirection.turnNorth()
print("The current direction is \(currentDirection)")
print("The remembered direction is \(rememberedDirection)")
// Prints "The current direction is north"
// Prints "The remembered direction is west"
Swift
복사
rememberedDirection 이 currentDirection 의 값으로 할당 되었을때, 실제로는 그값에 대한 복제가 일어납니다. currentDirection 의 값을 변경해도, rememberedDirection 의 값은 변경되지 않습니다.
Classes Are Reference Types
value type 과는 달리, reference type 은 변수 또는 상수에 할당되거나 함수에서 호출되었을 때 복제가 일어나지 않습니다. 반대로 class는 같은 객체를 참조합니다.
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0
Swift
복사
이 객체를 새로운 상수에 할당한후 상수의 프로퍼티를 변경해보겠습니다.
let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0
Swift
복사
클래스는 참조 타입이므로 같은 객체를 참조하게되고 하나를 변경하면 같은 객체를 참조하는 모든 상수 또는 변수의 값이 변경됩니다.
print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0"
Swift
복사
원본의 값또한 변경되는 것을 볼 수 있습니다.
class 를 다룰 때에는 이러한 점들을 주의해야합니다. 만약 코드내에서 tenEighty 와 alsoTenEighty 가 멀리 떨어져 있다면, 한쪽값을 변경할 때마다 다른 쪽을 신경써주어야합니다. 반대로 value type 은 이러한 사실을 주의하지 않아도 됩니다.
tenEighty 와 alsoTenEighty 둘다 상수로 선언된 것을 볼 수 있습니다. 그러나 여전히 둘의 프로퍼티를 변경할 수 잇습니다. 이는 tenEighty 와 alsoTenEighty 의 값 자체가 실제로 변하는 것이 아니기 때문입니다. tenEighty 와 alsoTenEighty 은 VideoMode 의 객체를 '저장' 하지 않고 '참조'합니다. 참조 대상을 변하지 않는 이상 상수로 사용이 가능합니다.
Identity Operators
클래스들은 참조타입이기 떄문에, 클래스의 하나의 객체를 여러 상수 또는 변수가 참조하도록 할 수 있습니다. ( 스트럭쳐와 열거형은 불가능합니다.)
같은 클래스의 객체를 참조하는 지 연산자를 활용해 확인해 볼 수 있습니다.
•
Identical to (===)
•
Not identical to (!==)
이 연산자를 사용해 참조대상이 같은지 확인할 수 있습니다.
if tenEighty === alsoTenEighty {
print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."
Swift
복사
== 와 === 는 다른 연산자입니다.
=== 는 같은 대상을 정확히 참조하는 지를 판단하고
== 는 클래스의 모든 프로퍼티 값이 동등한지 판단합니다.
Pointers
C와 C++ Objective C 와 같은 언어에서는 memory 관리를 위해 pointer 를 사용해보았을 수도 있을 것입니다. Swift의 참조타입의 객체를 참조하는 상수와 변수는 C의 pointer 변수와 매우 유사합니다. 하지만 이는 메모리의 주소를 직접적으로 가리키지 않습니다. 또한 * 기호를 사용하지 않아도 됩니다. 대신 이러한 참조는 여타 다른 상수와 변수들처럼 사용됩니다.