스위프트의 구조체와 클래스

개요


구조체와 클래스는 데이터들을 묶어서 표현할 때 사용한다. 사용자 정의 자료형을 만들어주는 것으로 볼 수 있다.

다른 언어와는 달리 하나의 파일 안에 구조체와 클래스를 모두 사용할 수 있고 둘 다 많이 쓰인다.

구조체와 클래스는 스위프트에서 객체지향 프로그래밍적 요소에 속한다.




객체지향? 인스턴스


객체지향 프로그래밍의 목적중의 하나인 캡슐화를 위해, 클래스에서는 더 나아가 상속까지 사용할 수 있다.

객체 또는 인스턴스는 일종의 블록으로 쉽게 사용하고 재사용할 수 있는 독립적인 기능 모듈이다.

애플 공식문서에서는 인스턴스라는 표현을 사용하므로 스위프트에서는 객체 대신 인스턴스라고 하는게 맞는것 같다.

작업을 수행하기 위한 인스턴스에서 접근되고 호출되는 프로퍼티와 매서드로 구성된다.




구조체


구조체는 struct 키워드를 사용해서 선언할 수 있다. 구조체의 이름은 대문자 카멜케이스, 구조체 안의 프로퍼티와 메서드는 소문자 카멜케이스를 사용하여 명명한다.

스위프트의 기본 자료형은 모두 구조체로 정의되어 있다.

전달인자로 값을 전달해도 값이 복사되어 전달될 뿐 함수 내부에서 기존 값 변경이 불가능하다.

1
2
3
4
5
6
7
8
9
10
struct SomeStructure {
  var ex1: String
  var ex2: Int
}

var defStructure: SomeStructure = SomeStructure("kyujin", 25)
defStructure.ex1 = "42seoul" //ok

let defStructure2: SomeStructure = SomeStructure("kyujin", 25)
defStructure2.ex1 = "42seoul" //error




클래스


클래스를 선언할 때는 class 키워드를 사용한다.

클래스의 인스턴스는 참조타입이기 때문에 상수로 선언해도 변경이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SomeClass {
  var name: String
  var age: Int
  
  deinit {
    print("delete Class")
  }
}

var exClass: SomeClass? = SomeClass()
exClass.name = "kyujin" //ok

let exClass2 = SomeClass()
exClass2.name = "kyujin" //ok

exClass = nil //deinit 메모리 해제




구조체와 클래스의 비교


  구조체 클래스
형식 값 형식 참조 형식
속성 구현 O O
생성자 구현 O O
소멸자 구현 X O
메소드 구현 O O
서브스크립트 구현 O O
익스텐션 O O
프로토콜 채용 O O
상속 X O
참조 카운팅 X O



구조체와 클래스의 공통점


  • 값을 저장하기 위해 프로퍼티들을 정의한다.
  • 함수적인 기능을 제공하기 위해 메서드를 정의한다.
  • 서브스크립트를 통해 프로퍼티에 접근할 수 있다.
  • 초기화 할때 초기 상태를 정의할 수 있다.
  • 필요할 때 확장할 수 있다.
  • 특정 종류의 표준 기능을 제공하기 위한 프로토콜을 준수한다.
  • 정의하는 방법, 문법, 인스턴스화 하는 방법이 같다.



구조체와 클래스의 차이점


  • 구조체는 상속이 불가능하고 클래스는 가능하다.
  • 타입 캐스팅은 클래스의 인스턴스만 가능하다.
  • 인스턴스의 메모리를 해제하는 Deinitializers는 클래스에서만 가능하다.
  • 참조 횟수 계산은 클래스의 인스턴스에만 가능하다.
  • 구조체는 값 타입, 클래스는 참조 타입이다.




구조체와 클래스의 선택




구조체 선택할 때


  • 연관된 값들의 캡슐화가 목적일 때
  • 캡슐화된 값을 복사하는 것이 효율적일 때
  • 구조체의 프로퍼티가 값타입이며 참조보다 복사하는게 효율적일 때
  • 상속이 필요없을 때




클래스의 상속


스위프트에서도 다른언어와 같이 클래스가 있고 클래스를 상속받을 수 있다.

스위프트에서는 상속받는 클래스를 subclass라고 부르며 상속하는 클래스를 superclass라고 부른다.

c++의 상속과 별 다른건 없어보인다.




Base Class


아무것도 상속받지 않은 클래스를 Base Class라고 한다.

1
2
3
4
5
6
7
8
9
class Vehicle {
  var currentSpeed = 0.0
  var description: String {
    return "current speed is \(currentSpeed)"
  }
  func MakeNoise() {
    //do nothing - will be override in subclasses
  }
}




클래스의 상속


위의 Vehicle 클래스를 상속받아보겠다.

상속 받고 superclass의 메서드들을 재정의 하고 싶다면 override라는 키워드를 앞에 사용하면 된다.

subclass에서 superclass의 요소를 불러오고 싶다면 super키워드를 사용하면 되고 자신은 self키워드를 사용하면 된다.

만약 superclass에서 재정의를 하지 않는다는 것을 명시하려면 final 키워드를 앞에 붙이면된다.

1
2
3
4
5
6
class Bicycle: Vehicle {
  var hasBasket = false
  override func MakeNoise() {
    print("따르릉")
  }
}