[iOS][Swift] Class 와 Struct

Youngkyu·2021년 8월 24일
0
post-thumbnail
post-custom-banner

클래스와 구조체(Class and Structure)


  • 클래스와 구조체는 프로그램 코드 블럭을 만들도록 유연하게 구성하는 것이 일반적인 목적이다.
  • 다른 언어와 달리 Swift는 사용자 클래스와 구조체를 위한 인터페이스 파일과 구현 파일을 따로 나누어 만들 필요가 없다.
  • 단일 파일에 클래스나 구조체를 정의하고, 외부 인터페이스로 다른 코드에 사용하기 위한 클래스와 구조체는 자동으로 만들어진다.

클래스와 구조체의 공통점


  • 여러 변수를 담을 수 있는 컨테이너
  • 데이터를 용도에 맞게 묶어 표현하고자 할때 용이함
  • 프로퍼티와 메소드를 사용하여 구조화된 데이터와 기능을 가짐
  • 하나의 새로운 사용자 정의 데이터 타입을 만듬
  • 초기화, 확장(extension) 가능
  • 프로토콜 사용 가능
  • **서브스크립트(subscript) 사용** 가능
  • "."을 사용해 하위의 프로퍼티에 접근 가능

기본 형태


struct Resolution {
    var width = 0
    var height = 0
}
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String? //옵셔널 String 값으로 기본값은 nil
}

인스턴스 생성


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

구조체와 클래스는 인스턴스를 생성하는 방법이 같음. 다음처럼 인스턴스를 생성하면 모든 변수는 해당 구조체 또는 클래스에 작성되어있는 기본값으로 초기화됨.

속성 접근(Accessing Properties)


println("width of someResolution is \(someResolution.width)")
// "width of someResolution is 0"

"."으로 인스턴스의 속성에 접근할 수 있음.

println("width of someResolution is \(someVideoMode.resolution.width)")
// "width of someResolution is 0"

위 예제처럼 VideoMode의 resolution 속성에 width속성에 접근도 가능


someVideoMode.resolution.width = 1920
println("width of someResolution is \(someVideoMode.resolution.width)")
// "width of someResolution is 1920"

Objective-C와는 다르게, Swift는 직접 구조체 속성의 내부 속성을 설정하는 것이 가능함. 마지막 예제에서 someVideoMode의 resolution 속성의 width 속성은 직접 설정하며 resolution 속성 전체에 새로운 값을 설정할 필요가 없음.

구조체는 값 타입


Swift에서 모든 구조체는 상수나 변수에 할당하거나 함수에 넘겨질 때 값이 복사가 됨

let fhd = Resolution(width: 1920, height: 1080)
var screen = fhd

위 예제에서 fhd는 width, height가 각각 1920, 1080으로 초기화된 Resolution의 인스턴스로 선언되었다. 따라서 값만 본다면 screen.width = fhd.width이므로 같은 객체를 가리키는 것 같지만 둘은 엄연히 다른 인스턴스임.

C언어의 Call by Value와 비슷함

클래스는 참조 타입


값을 복사하는 구조체와 달리 Class는 같은 인스턴스에 대한 참조를 넘김

let best = VideoMode()
best.resolution = fhd
best.name = "1080p"
best.frameRate = 30

let bestTwo = better
bestTwo.frameRate = 60

println("frameRate of best is \(best.framerate)")
// "frameRate of best is 60"
println("frameRate of bestTwo is \(bestTwo.framerate)")
// "frameRate of bestTwo is 60"

C언어의 Call by Reference와 유사

식별 연산자(Identity Operators)


클래스는 참조 타입이기 때문에 여러 상수나 변수가 하나의 클래스 인스턴스를 참조하는 것이 가능함.

식별 연산자는 두 개의 상수나 변수가 같은 클래스 인스턴스를 참조하는지 찾을 때 유용함.

  • 동일한(===)
  • 동일하지 않은(!==)
if best === bestTwo {
	println("best === bestTwo")
}
// "best === bestTwo"

위는 두 상수나 변수가 같은 인스턴스를 참조하는지 확인하는 예제

"동일한"(===)과 "같은"(==)은 같은 의미가 아님

  • "동일한" 의미는 클래스 타입의 두 상수나 변수가 정확하게 같은 클래스 인스턴스를 참조한다는 의미.
  • "같은" 의미는 두 인스턴스가 같은 값을 가지고 있음을 의미함.

포인터(Pointer)


C, C++, Objective-C에서, 메모리 주소를 참조하기 위해 포인터를 사용한다. C의 포인터와 유사하게 Swift 상수나 변수는 특정 참조 타입의 인스턴스를 참조하지만, 메모리 주소에 직접 가르키진 않으며, 참조를 만들 때 별표(*)를 사용하여 나타낼 필요가 없음.

대신 참조는 Swift의 다른 상수나 변수처럼 정의됨.

참고


클래스와 구조체 중 선택하기(Choosing Between Classes and Structures)

프로그램 코드의 구성된 블럭으로서 사용자 데이터 타입으로 정의하는 클래스나 구조체를 사용할 수 있음.

그러나 구조체 인스턴스는 항상 값을 넘기며, 클래스 인스턴스는 항상 참조를 넘겨줌.
이 의미는 서로 다른 작업의 종류에 적합하다는 의미.
프로젝트에 필요한 데이터 구조와 기능을 고려하여, 각각의 데이터는 클래스나 구조체로 정의하도록 구성해야 함.

구조체를 생성 시 아래의 조건에 한 가지 이상일 경우 적용하면 좋음.

  • 구조체의 최우선 목표는 몇몇 단순 데이터 값을 캡슐화 하는 경우
  • 캡슐화된 값이 그 구조체의 인스턴스가 할당되거나 넘겨질 때 참조보다 복사하는 것일 경우
  • 구조체에 저장되는 값 속성이 참조보다 복사가 예상되는 값 타입인 경우
  • 다른 기존 타입에서 기능이나 속성이 상속될 필요가 없는 경우

다음은 구조체가 포함하면 좋은 속성 예제.

  • Double 타입인 width 속성과 height 속성을 캡슐화하는 기하학 모형의 크기
  • Int 타입인 start 속성과 length 속성을 캡슐화하는 시리즈의 범위를 참조하는 방법
  • Double 타입인 x, y와 z 속성을 캡슐화하는 3D 좌표 시스템.

문자열, 배열 그리고 딕셔너리를 위한 할당과 복사(Assignment and Copy Behavior for Strings, Arrays and Dictionaries)

Swift의 문자열, 배열 그리고 딕셔너리 타입은 구조체로 구현되어있음.
문자열, 배열 그리고 딕셔너리는 새로운 상수나 변수에 할당하거나 함수나 메소드에 넘겨줄 때 복사된다는 의미.

이러한 행동은 FoundationNSString, NSArray 그리고 NSDictionary과는 다른데 이 것들은 구조체가 아니라 클래스로 구현이 되었음. NSString, NSArray 그리고 NSDictionary 인스턴스는 복사보단 기존 인스턴스에 참조를 언제나 할당하고 넘겨줌.

참고 링크

profile
iOS를 공부하고 있는 대학생입니다.
post-custom-banner

0개의 댓글