본문 바로가기

Swift 문법정리

1.1 Classes and Structures 정리

Classes and Structures 정리

1.1 Classes and Structures 기본 형태

struct Resolution {
       // 내용
}

class VideoMode {
       // 내용
}

 

구조체나 클래스의 이름은 첫 글자는 대문자로 쓰고 카멜 표기법으로 작성합니다. 축약이 된 형태라면 대문자로 작성이 가능하며 속성, 메서드는 소문자로 시작합니다. 언더바는 사용을 자제하는 것이 좋습니다. 

1.2 Property and Method

struct Resolution {
       var width = 0
       var height = 0
       
       func checkResolution () -> String {
            return "확인"
       }
}

class VideoMode {
      var interlaced = falase
      var frameRate = 0.0
      var name : String?
      
      func checkVideoMode () -> String {
           return "미확인"
       }
}

 

구조체나 클래스 안에 들어간 변수나 상수는 속성(Property),  함수는 메서드(Method)라고 불립니다. 일반 변수, 상수, 함수와는 구조, 문법에는 차이가 없지만 구조체, 클래스 안에서 정의된다는 점만 다릅니다. 

1.3 Instance

구조체나 클래스는 그대로 사용하는 것이 불가능합니다. 위의 예제 역시 단순히 객체에 대한 정의만 했을 뿐 실제로 값을 저장하고 메서드를 호출하는 공간은 할당받지 못했습니다. 구조체나 클래스는 값을 담는 그릇이 아닌 틀이고 이 틀을 바탕으로 만든 그릇을 인스턴스라고 합니다. 인스턴스를 만들고 이 곳에 실질적인 값을 담을 수 있습니다.

 

let someResolution = Resolution()

let someVideoMode = VideoMode()

 

위의 예제는 Resolution, VideoMode의 인스턴스를 만든 예시입니다. 구조체나 클래스 이름 뒤에 ()를 붙이면 초기화가 되면서 인스턴스가 생성되고 이를 변수나 상수에 할당하면  Resolution, VideoMode의 인스턴스가 생성됩니다. 함수 호출과 비슷하지만 실질적인 내용은 다릅니다.

 

var width = someResolution.width

var frameRate = someVideoMode.frameRate

 

위 예제에서와 같이 구조체와 클래스의 속성에 접근하기 위해서는 인스턴스를 통해서만 접근이 가능합니다. Resolution, VideoMode와 같이 구조체와 클래스의 이름으로 접근하면 접근이 불가능하고 someResolution, someVideoMode와 같이 인스턴스의 이름을 통해서만 접근이 가능합니다. 속성에 접근하기 위해서는. 을 이용하여 접근합니다. 

 

class VideoMode {
      var interlaced = falase
      var frameRate = 0.0
      var name : String?
      
      var in = Resolution ()
      
      func checkVideoMode () -> String {
           return "미확인"
       }
}

let someVideoMode = VideoMode()

someVideoMode.in.width

 

만약 클래스의 내용이 조금 바뀌어 someVideoMode 인스턴스를 통해 Resolution의 width에 접근한다고 한다면 새로 추가된 var in Resolution()은 클래스 videoMode안에 인스턴스가 있으므로 someVideoMode -> in (Resolution의 인스턴스) -> width 이와 같이 상위에서 하위 순서대로 접근해야 합니다. 이와 같은 방식을 체인이라고 합니다. 

1.4 Initialize

클래스, 구조체의 모든 속성은 인스턴스가 생성되는 지점에서 반드시 초기화되어야 합니다. 구조체는 속성 값을 인자 값을 통해 초기화가 가능한 Memberwise Initializer이라는 초기화 구문을 제공합니다. 

 

let someResolution = Resolution(width : 1024, height : 768)

 

위의 예시는 Resolution 구조체를 Memberwise Initializer로 초기화했습니다. Resolution 내의 2개의 속성 width, height를 인자값을 받아 초기화했습니다. 기존 width, heigth의 초기값은 0이었지만 Memberwise Initializer를 통해 width : 1024, height : 768로 초기화되었습니다.

Resolution()에서 () 역시 초기화 구문입니다. 그러나 어떠한 인자 값도 전달하지 않기 때문에 구조체는 선언과 초기화가 완료되어있어야만 초기화 구문으로 사용이 가능합니다.

 

Resolution ()
//인자값이 없기 때문에 속성을 초기화하지 않기 때문에 기본적으로 모든 속성이 선언과 초기화가 되어있어야합니다

Resolution(width : 1024, height : 768)
// 모든 속성의 초기값을 입력받아 모든 속성을 초기화 시킵니다

 

1.5 구조체의 복사와 클래스의 참조

구조체와 클래스의 가장 큰 차이는 복사와 참조에 있습니다. 먼저 구조체는 복사하여 전달하는 방식을 사용합니다. 인스턴스를 변수나 상수에 대입하면 기존의 인스턴스가 그대로 대입되는 것이 아닌 복사하여 새로운 독립적인 형태로 나타납니다. 이는 어느 한쪽을 변경하더라도 서로에게 어떠한 영향도 미치지 않습니다.  

 

let hd = Resolution (width : 1920, height : 1080) // width = 1920
var cinema = hd
cinema.width = 2048 // width = 2048

 

Resolution은 구조체임으로 상수 hd에 넣는 순간 인스턴스가 생성되며 변수 cinema 역시 hd 가 Resolution의 구조체를 가지고 있기 때문에 변수 cinema도 인스턴스가 생성됩니다. 구조체는 앞서 언급했듯이 복사를 하기 때문에 hd 인스턴스와 cinema 인스턴스는 서로 어떠한 영향도 미치지 않습니다. hd 인스턴스는 width를 1920주고 cinema width는 2048을 주었지만 hd 인스턴스의 값은 1920 그대로입니다. 

 

let hd = Resolution (width : 1920, height : 1080)
hd.width = 4096

 

인스턴스를 상수에 할당할 것인지 변수에 할당할 것인지도 매우 중요합니다. 구조체는 인스턴스를 복사해오는 구조이기 때문에 상수에 할당할 경우 속성 값을 변경하게 되면 저장된 값 자체가 변경되는 것으로 인식하기 때문에 변경을 할 수 없게 됩니다. 저장된 값 자체를 변경할 수 있는 것은 변수만 가능합니다. 

 

class VideoMode {
      var interlaced = falase
      var frameRate = 0.0
      var name : String?
      
      func checkVideoMode () -> String {
           return "미확인"
       }
}

let tenEighty = VideoMode ()

tenEighty.resoultuion = hd
tenEighty.interlaced = = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsotenEighty = tenEighty

alsotenEighty.frameRate = 30.0
tenEighty.frameRate // 30

 

VideoMode의 인스턴스 상수 tenEighty를 만든 후에 tenEighty를 alsoTenEighty 상수에 넣고 alsoTenEighty.frameRate =30.0으로 바꿨습니다. 클래스는 참조 형식이기 때문에 tenEighty.frameRate // 30역 시 30으로 바뀐 것을 확인할 수 있습니다.

 

단일한 사용이 보장되는 구조체의 경우 인스턴스를 할당한 변수나 수가 끝나면 메모리를 해제해도 되지만 클래스 인스턴스의 경우는 여러 곳에서 동시에 참조가 가능하기 때문에 함부로 메모리를 해제할 수 없기에 메모리 문제가 발생합니다. 스위프트에서는 Auto Reference Counter(ARC)라는 객채를 도입하여 변수, 상수, 함수의 인자 값으로 할당되면 1 증가하고 종료하면 카운트를 1 감소시키는 작업을 하며 0이 되면 메모리를 해제시킵니다.

 

=== // 동일한 인스턴스인지 확인할 때
!== // 동일한 인스턴스가 아닌지 확인할 때
 
if (tenEighty === alsoTenEighty) {
    print ("동일")
}else {
    print ("불일치")
}
// 동일

 

클래스는 참조 타입이기 때문에 두 인스턴스가 같은 메모리 주소를 참조하는지 안하는지 확인이 필요할 때가 있습니다. 이때 ===, !==를 사용하여 확인이 가능합니다. VideoMode는 tenEighty를 상수에 참조하였고 tenEighty는 다시 alsoTenEighty를 참조하였기 때문에 tenEighty, alsoTenEighty는 같은 메모리주소를 참조하기 때문에 True를 반환합니다.

 

let one = VideoMode ()
let two = VideoMode ()

if (one === two) {
    print ("동일")
}else {
    print ("불일치")
}
// 불일치

 

상수 two에 할당된 인스턴스는 one에 할당된 인스턴스가 아닌 새롭게 생성된 인스턴스입니다. VideoMode의 인스턴스는 맞지만 같은 메모리 주소를 참조하는 것은 아니기 때문에 False를 반환합니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'Swift 문법정리' 카테고리의 다른 글

1.3 Classes and Structures Method정리  (0) 2020.05.21
1.2 Classes and Structures Property 정리  (0) 2020.05.14
Function 정리  (0) 2020.05.11
Collection Types 정리  (0) 2020.05.08
Optional 정리  (0) 2020.05.08