[Swift] 9. Structures and Classes

도윤·2021년 7월 19일
0

Swift

목록 보기
13/21

Comparing Structures and Classes

공통점

  • 값을 저장할 프로퍼티 선언 가능
  • 함수적 기능하는 메소드 정의 가능
  • 내부 값에 첨자 구문을 사용해 접근 가능
  • 생성자를 사용해 초기 상태 설정 가능
  • 프로토콜 채택하여 표준 기능 제공 가능

차이점(class에만 존재)

  • 한 클래스가 다른 클래스의 특성을 사용하는 상속 사용 가능
  • 타입 캐슽팅을 통해 클래스의 인스턴스 타입을 런타임에서 확인 가능
  • Deinitializer를 사용하여 할당된 어떤 자원도 할당을 없앨 수 있다.
  • 클래스 인스턴스의 Reference Counting(참조 횟수) 둘 이상 허용

Definition Syntax

구조체와 클래스 비슷하게 선언.
선언할 때 UpperCamelCase를 이용하는 것이 좋음.

struct SomeStructure {
    // structure definition goes here
}
class SomeClass {
    // class definition goes here
}

Strucure and Class instances

정의된 구조체와 클래스를 사용하기 위해서는 인스턴스를 만들어서 사용해야 한다

let someResolution = Resolution()
let someVideoMode = VideoMode()

인스턴스를 만드는 방법은 위의 코드와 같다. 가장 간단한 방법은 구조체나 클래스의 이름을 쓰고 뒤에 ()를 붙이는 것이다. 이렇게 하면 default 값으로 구조체,클래스의 인스턴스를 생성한다.

Accessing Properties

프로퍼티에 접근하려면 .을 사용하면 된다

print("The width of someResolution is \(someResolution.width)")
// Prints "The width of someResolution is 0

아까 선언한 someVideoMode 클래스의 resolution 프로퍼티는 구조체였다. 이럴 때 resolution 프로퍼티의 프로퍼티에 접근하기 위해선 또 .을 쓰면 된다.

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’

Memberwise Initailizers for Structure Types

모든 구조체에는 새로운 구조체 인스턴스의 프로퍼티를 초기화하기 위해 자동적으로 생성되는 Memberwise Initializer가 존재. 새로운 인스턴스의 초기화 값은 프로퍼팉의 이름으로 초기화할 수 있다.

let vga = Resolution(width:630, height : 480)

클래스는 deault memberwise initializer가 없어서 생성자를 직접 선언하여 초기화해줘야 한다.


Structures and Enumerations Are Value Types

Value Type, 즉 값 타입은 변수,상수에 할당되거나 함수에 전달될 때 값이 복사되는 것을 말한다.
Int,Double,Float,Bool,String,Array,Dictionary는 Value Type이다. 또한 모든 구조체와 열거형은 값타입이다. 이는 모든 구조체,열거형 인스턴스는 값 타입이고 그것들의 프로퍼티는 항상 복사되며 전달된 다는 것이다.

Array,Dictionary,String과 같이 표준 라이브러리에 의해 정의된 컬렉션 타입은 최적화를 통해 복사비용을 줄였다. 이런 컬렉션은 원본을 볷가하지 않고 원본 인스턴스와 복사본 사이에 저장되는 메모리를 공유한다.
만약 복사본,즉 컬렉션이 수정되려고 하면 수정 직전에 원본을 복사한다. 이렇기 때문에 코드에서는 즉시 복사된 것 처럼 보인다.

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

위에 선언한 Resolution의 구조체의 인스턴스를 hd로 선언한다. 하나의 변수 cinema를 선언해서 인스턴스를 할당한다. 결과는 같은 값을 가지는 두가지 인스턴스로 분리된다. 그러나 같은 Instance value를 가져도 cinema의 프로퍼티를 변경해도 hd의 값에 변화는 발생하지 않는다.

열거형도 동일하게 나타난다.

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

Classes Are Reference Types

구조체와 다르게 클래스는 참조 타입니다.
참조 타입이란 변수나 상수에 할당될 때 인스턴스가 복사되는 것이 아니라 메모리의 같은 부분을 참조하는 것이다.

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

alsoTenEighty를 변경하면 참조하고 있는 메모리의 값이 변경된다.
따라서 tenEighty의 frameRate 또한 30.0으로 변경된다.

Identity Operators

클래스는 참조타입이기 때문에 여러 상수나 변수가 동일한 클래스 인슽턴스를 참조할 수 있다.
===,!== 을 통해 같은 인스턴스를 참조하는지 비교할 수 있다.

if tenEighty === alsoTenEighty {
    print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")
}
// Prints "tenEighty and alsoTenEighty refer to the same VideoMode instance.

Pointers

C,C++,Objective-C에서처럼 이러한 참조가 포인터를 사용한 다는 것을 알 수 있다.
일부 참조타입의 인스턴스를 가지는 상수,변수는 C의 포인터와 비슷하지만 메모리에 대한 직접적인 포인터가 아니기 때문에 *를 쓰지 않아도 된다.

0개의 댓글